@hot-updater/react-native 1.0.0-rc.16 → 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.
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +491 -388
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +5 -11
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +290 -12
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +35 -19
- package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
- package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
- package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
- package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +110 -52
- package/android/src/main/java/com/hotupdater/PreviousProcessExit.kt +89 -0
- package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
- package/android/src/newarch/HotUpdaterModule.kt +74 -69
- package/android/src/oldarch/HotUpdaterModule.kt +63 -59
- package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +1 -1
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +446 -61
- package/android/src/test/java/com/hotupdater/HotUpdaterExceptionTest.kt +220 -0
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +19 -27
- package/android/src/test/java/com/hotupdater/InstallIdentityServiceTest.kt +71 -0
- package/android/src/test/java/com/hotupdater/KeyValueStorageServiceTest.kt +106 -0
- package/android/src/test/java/com/hotupdater/NoBackupContext.kt +11 -0
- package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +309 -23
- package/android/src/test/java/com/hotupdater/PreviousProcessExitTest.kt +57 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +238 -157
- package/ios/HotUpdater/Internal/BundleMetadata.swift +3 -53
- package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +8 -18
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +48 -29
- package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +108 -1
- package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
- package/lib/commonjs/appReady.js +111 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/appReady.spec.js +360 -0
- package/lib/commonjs/appReady.spec.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
- package/lib/commonjs/appReady.test-utils.js.map +1 -0
- package/lib/commonjs/baseURL.js +16 -0
- package/lib/commonjs/baseURL.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +104 -56
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +337 -74
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/commonjs/clientPlugin.js +49 -0
- package/lib/commonjs/clientPlugin.js.map +1 -0
- package/lib/commonjs/entryImportGraph.spec.js +50 -0
- package/lib/commonjs/entryImportGraph.spec.js.map +1 -0
- package/lib/commonjs/fetchJSON.js +2 -6
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/httpClient.js +18 -165
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/httpClient.spec.js +26 -199
- package/lib/commonjs/httpClient.spec.js.map +1 -1
- package/lib/commonjs/index.js +49 -36
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +108 -123
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +67 -48
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +80 -58
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/pluginHost.js +208 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/pluginHost.spec.js +292 -0
- package/lib/commonjs/pluginHost.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/eventId.js +129 -0
- package/lib/commonjs/plugins/insights/eventId.js.map +1 -0
- package/lib/commonjs/plugins/insights/eventId.spec.js +47 -0
- package/lib/commonjs/plugins/insights/eventId.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/index.js +272 -0
- package/lib/commonjs/plugins/insights/index.js.map +1 -0
- package/lib/commonjs/plugins/insights/insights.spec.js +640 -0
- package/lib/commonjs/plugins/insights/insights.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/sender.js +128 -0
- package/lib/commonjs/plugins/insights/sender.js.map +1 -0
- package/lib/commonjs/plugins/insights/sender.spec.js +265 -0
- package/lib/commonjs/plugins/insights/sender.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/state.js +145 -0
- package/lib/commonjs/plugins/insights/state.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +13 -2
- package/lib/commonjs/releaseCatalogCache.js.map +1 -1
- package/lib/commonjs/releaseCatalogCache.spec.js +18 -0
- package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/updateError.js +132 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/updateError.spec.js +149 -0
- package/lib/commonjs/updateError.spec.js.map +1 -0
- package/lib/commonjs/wrap.js +43 -25
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.progress.spec.js +195 -0
- package/lib/commonjs/wrap.progress.spec.js.map +1 -0
- package/lib/commonjs/wrap.spec.js +94 -230
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/appReady.js +103 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/appReady.spec.js +359 -0
- package/lib/module/appReady.spec.js.map +1 -0
- package/lib/module/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
- package/lib/module/appReady.test-utils.js.map +1 -0
- package/lib/module/baseURL.js +11 -0
- package/lib/module/baseURL.js.map +1 -0
- package/lib/module/checkForUpdate.js +103 -57
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +337 -74
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/module/clientPlugin.js +44 -0
- package/lib/module/clientPlugin.js.map +1 -0
- package/lib/module/entryImportGraph.spec.js +50 -0
- package/lib/module/entryImportGraph.spec.js.map +1 -0
- package/lib/module/fetchJSON.js +2 -6
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/httpClient.js +18 -165
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/httpClient.spec.js +27 -200
- package/lib/module/httpClient.spec.js.map +1 -1
- package/lib/module/index.js +44 -38
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +108 -123
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +63 -44
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +80 -58
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/pluginHost.js +200 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/pluginHost.spec.js +291 -0
- package/lib/module/pluginHost.spec.js.map +1 -0
- package/lib/module/plugins/insights/eventId.js +122 -0
- package/lib/module/plugins/insights/eventId.js.map +1 -0
- package/lib/module/plugins/insights/eventId.spec.js +47 -0
- package/lib/module/plugins/insights/eventId.spec.js.map +1 -0
- package/lib/module/plugins/insights/index.js +268 -0
- package/lib/module/plugins/insights/index.js.map +1 -0
- package/lib/module/plugins/insights/insights.spec.js +639 -0
- package/lib/module/plugins/insights/insights.spec.js.map +1 -0
- package/lib/module/plugins/insights/sender.js +123 -0
- package/lib/module/plugins/insights/sender.js.map +1 -0
- package/lib/module/plugins/insights/sender.spec.js +265 -0
- package/lib/module/plugins/insights/sender.spec.js.map +1 -0
- package/lib/module/plugins/insights/state.js +139 -0
- package/lib/module/plugins/insights/state.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +13 -2
- package/lib/module/releaseCatalogCache.js.map +1 -1
- package/lib/module/releaseCatalogCache.spec.js +18 -0
- package/lib/module/releaseCatalogCache.spec.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/updateError.js +126 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/updateError.spec.js +149 -0
- package/lib/module/updateError.spec.js.map +1 -0
- package/lib/module/wrap.js +43 -25
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.progress.spec.js +196 -0
- package/lib/module/wrap.progress.spec.js.map +1 -0
- package/lib/module/wrap.spec.js +93 -229
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +23 -0
- package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
- package/lib/typescript/commonjs/appReady.test-utils.d.ts +9 -0
- package/lib/typescript/commonjs/appReady.test-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/baseURL.d.ts +4 -0
- package/lib/typescript/commonjs/baseURL.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +15 -2
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/clientPlugin.d.ts +185 -0
- package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts +2 -3
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +2 -36
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +3 -6
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +29 -15
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +29 -0
- package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/eventId.d.ts +18 -0
- package/lib/typescript/commonjs/plugins/insights/eventId.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/index.d.ts +40 -0
- package/lib/typescript/commonjs/plugins/insights/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/sender.d.ts +74 -0
- package/lib/typescript/commonjs/plugins/insights/sender.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/state.d.ts +46 -0
- package/lib/typescript/commonjs/plugins/insights/state.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +5 -1
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +34 -12
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/updateError.d.ts +26 -0
- package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +6 -10
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/appReady.d.ts +23 -0
- package/lib/typescript/module/appReady.d.ts.map +1 -0
- package/lib/typescript/module/appReady.test-utils.d.ts +9 -0
- package/lib/typescript/module/appReady.test-utils.d.ts.map +1 -0
- package/lib/typescript/module/baseURL.d.ts +4 -0
- package/lib/typescript/module/baseURL.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +15 -2
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/clientPlugin.d.ts +185 -0
- package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/module/fetchJSON.d.ts +2 -3
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +2 -36
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +3 -6
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +29 -15
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +29 -0
- package/lib/typescript/module/pluginHost.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/eventId.d.ts +18 -0
- package/lib/typescript/module/plugins/insights/eventId.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/index.d.ts +40 -0
- package/lib/typescript/module/plugins/insights/index.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/sender.d.ts +74 -0
- package/lib/typescript/module/plugins/insights/sender.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/state.d.ts +46 -0
- package/lib/typescript/module/plugins/insights/state.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +5 -1
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +34 -12
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/updateError.d.ts +26 -0
- package/lib/typescript/module/updateError.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +6 -10
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +14 -2
- package/plugins/insights/package.json +8 -0
- package/src/appReady.spec.ts +393 -0
- package/src/{notifyAppReadyInsights.test-utils.ts → appReady.test-utils.ts} +7 -7
- package/src/appReady.ts +149 -0
- package/src/baseURL.ts +15 -0
- package/src/checkForUpdate.releaseCatalog.spec.ts +370 -76
- package/src/checkForUpdate.ts +135 -80
- package/src/clientPlugin.ts +231 -0
- package/src/entryImportGraph.spec.ts +65 -0
- package/src/fetchJSON.ts +3 -10
- package/src/httpClient.spec.ts +30 -227
- package/src/httpClient.ts +20 -256
- package/src/index.spec.ts +117 -93
- package/src/index.ts +67 -52
- package/src/native.spec.ts +98 -72
- package/src/native.ts +93 -77
- package/src/pluginHost.spec.ts +297 -0
- package/src/pluginHost.ts +262 -0
- package/src/plugins/insights/eventId.spec.ts +60 -0
- package/src/plugins/insights/eventId.ts +171 -0
- package/src/plugins/insights/index.ts +367 -0
- package/src/plugins/insights/insights.spec.ts +732 -0
- package/src/plugins/insights/sender.spec.ts +287 -0
- package/src/plugins/insights/sender.ts +221 -0
- package/src/plugins/insights/state.ts +184 -0
- package/src/releaseCatalogCache.spec.ts +22 -0
- package/src/releaseCatalogCache.ts +19 -4
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +34 -13
- package/src/updateError.spec.ts +144 -0
- package/src/updateError.ts +153 -0
- package/src/wrap.progress.spec.ts +232 -0
- package/src/wrap.spec.ts +100 -283
- package/src/wrap.tsx +57 -26
- package/src/wrap.types.ts +6 -12
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -225
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.js +0 -188
- package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -378
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -171
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/commonjs/uuidv7.js +0 -41
- package/lib/commonjs/uuidv7.js.map +0 -1
- package/lib/commonjs/uuidv7.spec.js +0 -30
- package/lib/commonjs/uuidv7.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -224
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.js +0 -181
- package/lib/module/notifyAppReadyInsights.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.spec.js +0 -377
- package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -170
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/module/uuidv7.js +0 -36
- package/lib/module/uuidv7.js.map +0 -1
- package/lib/module/uuidv7.spec.js +0 -30
- package/lib/module/uuidv7.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -25
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/lib/typescript/commonjs/uuidv7.d.ts +0 -10
- package/lib/typescript/commonjs/uuidv7.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -25
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/uuidv7.d.ts +0 -10
- package/lib/typescript/module/uuidv7.d.ts.map +0 -1
- package/src/notifyAppReadyInsights.boundary.spec.ts +0 -242
- package/src/notifyAppReadyInsights.spec.ts +0 -362
- package/src/notifyAppReadyInsights.transport.spec.ts +0 -196
- package/src/notifyAppReadyInsights.ts +0 -293
- package/src/uuidv7.spec.ts +0 -25
- package/src/uuidv7.ts +0 -38
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
} from "@hot-updater/core";
|
|
8
8
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
9
9
|
|
|
10
|
+
import type { HotUpdaterClientHooks } from "./clientPlugin";
|
|
10
11
|
import type { HotUpdaterHttpClient } from "./httpClient";
|
|
12
|
+
import { InvalidUpdateResponseError, UpdateHttpError } from "./updateError";
|
|
11
13
|
|
|
12
14
|
const MINIMUM_RELEASE_ID = "00000000-0000-7000-8000-000000000001";
|
|
13
15
|
const RELEASE_ID = "00000000-0000-7000-8000-000000000002";
|
|
@@ -23,31 +25,38 @@ const SCOPE_KEY = createReleaseCatalogScopeKey({
|
|
|
23
25
|
strategy: "APP_VERSION",
|
|
24
26
|
});
|
|
25
27
|
|
|
26
|
-
const mocks = vi.hoisted(() =>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
const mocks = vi.hoisted(() => {
|
|
29
|
+
Reflect.set(globalThis, "HotUpdater", { SDK_VERSION: "test-sdk-version" });
|
|
30
|
+
return {
|
|
31
|
+
addListener: vi.fn(() => () => {}),
|
|
32
|
+
acceptReleaseCatalog: vi.fn(() => true),
|
|
33
|
+
commitReleaseSelection: vi.fn(async () => true),
|
|
34
|
+
getActiveUpdateState: vi.fn(() => ({
|
|
35
|
+
activeSelection: null as PersistedSelectionReceipt | null,
|
|
36
|
+
highestSeenCatalogs: {},
|
|
37
|
+
stableSelection: null as PersistedSelectionReceipt | null,
|
|
38
|
+
verificationPending: false,
|
|
39
|
+
})),
|
|
40
|
+
getAppVersion: vi.fn(() => "1.2"),
|
|
41
|
+
getBundleId: vi.fn(() => CURRENT_BUNDLE_ID),
|
|
42
|
+
getChannel: vi.fn(() => CHANNEL),
|
|
43
|
+
getCohort: vi.fn(() => "123"),
|
|
44
|
+
getCrashHistory: vi.fn(() => []),
|
|
45
|
+
getDefaultChannel: vi.fn(() => CHANNEL),
|
|
46
|
+
getFingerprintHash: vi.fn(() => null),
|
|
47
|
+
getInstallId: vi.fn(() => "install-id"),
|
|
48
|
+
getMinBundleId: vi.fn(() => MINIMUM_RELEASE_ID),
|
|
49
|
+
isChannelSwitched: vi.fn(() => false),
|
|
50
|
+
isReleaseSelectionCurrent: vi.fn(() => true),
|
|
51
|
+
resetChannel: vi.fn(),
|
|
52
|
+
stageBundle: vi.fn(
|
|
53
|
+
async (): Promise<{
|
|
54
|
+
delivery: "patch" | "manifest" | "archive";
|
|
55
|
+
patchFallback: boolean;
|
|
56
|
+
} | null> => ({ delivery: "manifest", patchFallback: false }),
|
|
57
|
+
),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
51
60
|
|
|
52
61
|
vi.mock("react-native", () => ({ Platform: { OS: "ios" } }));
|
|
53
62
|
|
|
@@ -86,16 +95,47 @@ const createClient = (catalog = createCatalog()) => {
|
|
|
86
95
|
archiveUrl: "https://updates.example.com/bundle.tar.br",
|
|
87
96
|
};
|
|
88
97
|
const resolveArtifact = vi.fn(async () => artifact);
|
|
89
|
-
const sendInsightsEvent = vi.fn(async () => undefined);
|
|
90
98
|
const session = {
|
|
91
99
|
fetchReleaseCatalog,
|
|
92
100
|
resolveArtifact,
|
|
93
|
-
sendInsightsEvent,
|
|
94
101
|
};
|
|
95
102
|
const client: HotUpdaterHttpClient = {
|
|
96
103
|
createSession: vi.fn(async () => session),
|
|
97
104
|
};
|
|
98
|
-
return { client, fetchReleaseCatalog, resolveArtifact
|
|
105
|
+
return { client, fetchReleaseCatalog, resolveArtifact };
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
type PluginEvent = {
|
|
109
|
+
[K in keyof HotUpdaterClientHooks]-?: [
|
|
110
|
+
K,
|
|
111
|
+
Parameters<NonNullable<HotUpdaterClientHooks[K]>>[0],
|
|
112
|
+
];
|
|
113
|
+
}[keyof HotUpdaterClientHooks];
|
|
114
|
+
|
|
115
|
+
/** Records what checks report to plugins, in order. */
|
|
116
|
+
const recordPluginEvents = async () => {
|
|
117
|
+
const { configurePlugins } = await import("./pluginHost");
|
|
118
|
+
const events: PluginEvent[] = [];
|
|
119
|
+
configurePlugins(
|
|
120
|
+
[
|
|
121
|
+
{
|
|
122
|
+
id: "recorder",
|
|
123
|
+
setup: () => ({
|
|
124
|
+
onUpdateCheck: (result) => {
|
|
125
|
+
events.push(["onUpdateCheck", result]);
|
|
126
|
+
},
|
|
127
|
+
onBundleDownloaded: (info) => {
|
|
128
|
+
events.push(["onBundleDownloaded", info]);
|
|
129
|
+
},
|
|
130
|
+
onUpdateError: (error) => {
|
|
131
|
+
events.push(["onUpdateError", error]);
|
|
132
|
+
},
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
{ baseURL: "https://updates.example.com" },
|
|
137
|
+
);
|
|
138
|
+
return events;
|
|
99
139
|
};
|
|
100
140
|
|
|
101
141
|
describe("checkForUpdate Release catalog protocol", () => {
|
|
@@ -112,59 +152,84 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
112
152
|
});
|
|
113
153
|
mocks.isReleaseSelectionCurrent.mockReturnValue(true);
|
|
114
154
|
mocks.commitReleaseSelection.mockResolvedValue(true);
|
|
115
|
-
mocks.
|
|
155
|
+
mocks.stageBundle.mockResolvedValue({
|
|
156
|
+
delivery: "manifest",
|
|
157
|
+
patchFallback: false,
|
|
158
|
+
});
|
|
116
159
|
});
|
|
117
160
|
|
|
118
|
-
it("reports
|
|
161
|
+
it("reports the check, then the download only after staging", async () => {
|
|
119
162
|
const { checkForUpdate } = await import("./checkForUpdate");
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
163
|
+
const events = await recordPluginEvents();
|
|
164
|
+
const { client } = createClient();
|
|
165
|
+
let complete!: (delivery: {
|
|
166
|
+
delivery: "patch" | "manifest" | "archive";
|
|
167
|
+
patchFallback: boolean;
|
|
168
|
+
}) => void;
|
|
169
|
+
mocks.stageBundle.mockImplementationOnce(
|
|
123
170
|
() =>
|
|
124
|
-
new Promise
|
|
171
|
+
new Promise((resolve) => {
|
|
125
172
|
complete = resolve;
|
|
126
173
|
}),
|
|
127
174
|
);
|
|
128
175
|
const update = await checkForUpdate({
|
|
129
176
|
client,
|
|
130
|
-
insights: true,
|
|
131
177
|
updateStrategy: "appVersion",
|
|
132
178
|
});
|
|
133
179
|
expect(update?.shouldForceUpdate).toBe(false);
|
|
180
|
+
expect(events).toEqual([
|
|
181
|
+
[
|
|
182
|
+
"onUpdateCheck",
|
|
183
|
+
{
|
|
184
|
+
status: "UPDATE_AVAILABLE",
|
|
185
|
+
channel: CHANNEL,
|
|
186
|
+
fromBundleId: CURRENT_BUNDLE_ID,
|
|
187
|
+
fromReleaseId: null,
|
|
188
|
+
toBundleId: TARGET_BUNDLE_ID,
|
|
189
|
+
toReleaseId: RELEASE_ID,
|
|
190
|
+
transitionKind: "INSTALL",
|
|
191
|
+
updateStatus: "UPDATE",
|
|
192
|
+
shouldForceUpdate: false,
|
|
193
|
+
updateStrategy: "appVersion",
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
]);
|
|
134
197
|
const pending = update!.updateBundle();
|
|
135
|
-
await vi.waitFor(() => expect(mocks.
|
|
136
|
-
expect(
|
|
137
|
-
complete(true);
|
|
198
|
+
await vi.waitFor(() => expect(mocks.stageBundle).toHaveBeenCalledOnce());
|
|
199
|
+
expect(events).toHaveLength(1);
|
|
200
|
+
complete({ delivery: "patch", patchFallback: true });
|
|
138
201
|
await expect(pending).resolves.toBe(true);
|
|
139
|
-
expect(
|
|
140
|
-
|
|
141
|
-
|
|
202
|
+
expect(events[1]).toEqual([
|
|
203
|
+
"onBundleDownloaded",
|
|
204
|
+
{
|
|
205
|
+
channel: CHANNEL,
|
|
142
206
|
fromBundleId: CURRENT_BUNDLE_ID,
|
|
143
|
-
toBundleId: TARGET_BUNDLE_ID,
|
|
144
207
|
fromReleaseId: null,
|
|
208
|
+
toBundleId: TARGET_BUNDLE_ID,
|
|
145
209
|
toReleaseId: RELEASE_ID,
|
|
146
210
|
updateStrategy: "appVersion",
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
211
|
+
delivery: "patch",
|
|
212
|
+
patchFallback: true,
|
|
213
|
+
},
|
|
214
|
+
]);
|
|
151
215
|
});
|
|
152
216
|
|
|
153
|
-
it.each([
|
|
154
|
-
"does not report a download when staging
|
|
217
|
+
it.each(["nothing new", "failure"])(
|
|
218
|
+
"does not report a download when staging brings %s",
|
|
155
219
|
async (result) => {
|
|
156
220
|
const { checkForUpdate } = await import("./checkForUpdate");
|
|
157
|
-
const
|
|
158
|
-
|
|
221
|
+
const events = await recordPluginEvents();
|
|
222
|
+
const { client } = createClient();
|
|
223
|
+
if (result === "nothing new")
|
|
224
|
+
mocks.stageBundle.mockResolvedValueOnce(null);
|
|
159
225
|
else
|
|
160
|
-
mocks.
|
|
226
|
+
mocks.stageBundle.mockRejectedValueOnce(new Error("download failed"));
|
|
161
227
|
const update = await checkForUpdate({
|
|
162
228
|
client,
|
|
163
|
-
insights: true,
|
|
164
229
|
updateStrategy: "appVersion",
|
|
165
230
|
});
|
|
166
231
|
await update!.updateBundle().catch(() => false);
|
|
167
|
-
expect(
|
|
232
|
+
expect(events.map(([name]) => name)).not.toContain("onBundleDownloaded");
|
|
168
233
|
},
|
|
169
234
|
);
|
|
170
235
|
|
|
@@ -201,7 +266,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
201
266
|
requestTimeout: undefined,
|
|
202
267
|
targetBundleId: TARGET_BUNDLE_ID,
|
|
203
268
|
});
|
|
204
|
-
expect(mocks.
|
|
269
|
+
expect(mocks.stageBundle).toHaveBeenCalledWith(
|
|
205
270
|
expect.objectContaining({
|
|
206
271
|
bundleId: TARGET_BUNDLE_ID,
|
|
207
272
|
archiveUrl: "https://updates.example.com/bundle.tar.br",
|
|
@@ -242,8 +307,8 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
242
307
|
},
|
|
243
308
|
],
|
|
244
309
|
});
|
|
245
|
-
const
|
|
246
|
-
|
|
310
|
+
const events = await recordPluginEvents();
|
|
311
|
+
const { client, resolveArtifact } = createClient(forceCatalog);
|
|
247
312
|
|
|
248
313
|
const result = await checkForUpdate({
|
|
249
314
|
client,
|
|
@@ -257,8 +322,8 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
257
322
|
});
|
|
258
323
|
await expect(result?.updateBundle()).resolves.toBe(true);
|
|
259
324
|
expect(resolveArtifact).not.toHaveBeenCalled();
|
|
260
|
-
expect(mocks.
|
|
261
|
-
expect(
|
|
325
|
+
expect(mocks.stageBundle).not.toHaveBeenCalled();
|
|
326
|
+
expect(events.map(([name]) => name)).not.toContain("onBundleDownloaded");
|
|
262
327
|
expect(mocks.commitReleaseSelection).toHaveBeenCalledWith({
|
|
263
328
|
guard: expect.objectContaining({ generation: 2, scopeKey: SCOPE_KEY }),
|
|
264
329
|
selection: expect.objectContaining({
|
|
@@ -268,7 +333,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
268
333
|
});
|
|
269
334
|
});
|
|
270
335
|
|
|
271
|
-
it("reports same-file
|
|
336
|
+
it("reports a same-file adoption as UNCHANGED with the adopted Release", async () => {
|
|
272
337
|
const active: PersistedSelectionReceipt = {
|
|
273
338
|
catalogId: CATALOG_ID,
|
|
274
339
|
bundleId: TARGET_BUNDLE_ID,
|
|
@@ -288,25 +353,25 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
288
353
|
verificationPending: false,
|
|
289
354
|
});
|
|
290
355
|
const { checkForUpdate } = await import("./checkForUpdate");
|
|
291
|
-
const
|
|
356
|
+
const events = await recordPluginEvents();
|
|
357
|
+
const { client } = createClient();
|
|
292
358
|
|
|
293
359
|
const result = await checkForUpdate({
|
|
294
|
-
insights: true,
|
|
295
360
|
client,
|
|
296
361
|
updateStrategy: "appVersion",
|
|
297
362
|
});
|
|
298
363
|
await result?.updateBundle();
|
|
299
364
|
|
|
300
|
-
expect(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
);
|
|
365
|
+
expect(events.at(-1)).toEqual([
|
|
366
|
+
"onUpdateCheck",
|
|
367
|
+
{
|
|
368
|
+
status: "UNCHANGED",
|
|
369
|
+
channel: CHANNEL,
|
|
370
|
+
bundleId: TARGET_BUNDLE_ID,
|
|
371
|
+
releaseId: RELEASE_ID,
|
|
372
|
+
previousReleaseId: MINIMUM_RELEASE_ID,
|
|
373
|
+
},
|
|
374
|
+
]);
|
|
310
375
|
});
|
|
311
376
|
|
|
312
377
|
it("selects a lower-id Release when explicitly switching scopes", async () => {
|
|
@@ -385,7 +450,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
385
450
|
});
|
|
386
451
|
await expect(result?.updateBundle()).resolves.toBe(true);
|
|
387
452
|
expect(resolveArtifact).not.toHaveBeenCalled();
|
|
388
|
-
expect(mocks.
|
|
453
|
+
expect(mocks.stageBundle).not.toHaveBeenCalled();
|
|
389
454
|
expect(mocks.commitReleaseSelection).toHaveBeenCalledWith({
|
|
390
455
|
guard: expect.objectContaining({
|
|
391
456
|
catalogHash: CATALOG_HASH,
|
|
@@ -416,7 +481,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
416
481
|
await expect(result?.updateBundle()).rejects.toBeInstanceOf(
|
|
417
482
|
StaleReleaseCatalogError,
|
|
418
483
|
);
|
|
419
|
-
expect(mocks.
|
|
484
|
+
expect(mocks.stageBundle).not.toHaveBeenCalled();
|
|
420
485
|
});
|
|
421
486
|
|
|
422
487
|
it("installs an older enabled Release as a forced rollback", async () => {
|
|
@@ -466,7 +531,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
466
531
|
transitionKind: "INSTALL",
|
|
467
532
|
});
|
|
468
533
|
await expect(result?.updateBundle()).resolves.toBe(true);
|
|
469
|
-
expect(mocks.
|
|
534
|
+
expect(mocks.stageBundle).toHaveBeenCalledWith(
|
|
470
535
|
expect.objectContaining({
|
|
471
536
|
bundleId: TARGET_BUNDLE_ID,
|
|
472
537
|
status: "ROLLBACK",
|
|
@@ -573,7 +638,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
573
638
|
}),
|
|
574
639
|
);
|
|
575
640
|
expect(resolveArtifact).not.toHaveBeenCalled();
|
|
576
|
-
expect(mocks.
|
|
641
|
+
expect(mocks.stageBundle).not.toHaveBeenCalled();
|
|
577
642
|
},
|
|
578
643
|
);
|
|
579
644
|
|
|
@@ -629,7 +694,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
629
694
|
);
|
|
630
695
|
expect(mocks.acceptReleaseCatalog).not.toHaveBeenCalled();
|
|
631
696
|
expect(mocks.commitReleaseSelection).not.toHaveBeenCalled();
|
|
632
|
-
expect(mocks.
|
|
697
|
+
expect(mocks.stageBundle).not.toHaveBeenCalled();
|
|
633
698
|
});
|
|
634
699
|
|
|
635
700
|
it("rejects an unexpected Catalog identity before accepting catalog state", async () => {
|
|
@@ -669,4 +734,233 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
669
734
|
);
|
|
670
735
|
expect(mocks.acceptReleaseCatalog).not.toHaveBeenCalled();
|
|
671
736
|
});
|
|
737
|
+
it("reports a check that found nothing to install as UNCHANGED", async () => {
|
|
738
|
+
mocks.getBundleId.mockReturnValueOnce(MINIMUM_RELEASE_ID);
|
|
739
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
740
|
+
const events = await recordPluginEvents();
|
|
741
|
+
const { client } = createClient(
|
|
742
|
+
createCatalog({ releases: [], rollbackReleases: [] }),
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
await expect(
|
|
746
|
+
checkForUpdate({ client, updateStrategy: "appVersion" }),
|
|
747
|
+
).resolves.toBeNull();
|
|
748
|
+
|
|
749
|
+
expect(events).toEqual([
|
|
750
|
+
[
|
|
751
|
+
"onUpdateCheck",
|
|
752
|
+
{
|
|
753
|
+
status: "UNCHANGED",
|
|
754
|
+
channel: CHANNEL,
|
|
755
|
+
bundleId: MINIMUM_RELEASE_ID,
|
|
756
|
+
releaseId: null,
|
|
757
|
+
previousReleaseId: null,
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
]);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it("treats a scope without a catalog as no update, not a failure", async () => {
|
|
764
|
+
const onError = vi.fn();
|
|
765
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
766
|
+
const events = await recordPluginEvents();
|
|
767
|
+
const { client, fetchReleaseCatalog } = createClient();
|
|
768
|
+
fetchReleaseCatalog.mockResolvedValueOnce(null as never);
|
|
769
|
+
|
|
770
|
+
await expect(
|
|
771
|
+
checkForUpdate({ client, onError, updateStrategy: "appVersion" }),
|
|
772
|
+
).resolves.toBeNull();
|
|
773
|
+
|
|
774
|
+
expect(onError).not.toHaveBeenCalled();
|
|
775
|
+
expect(mocks.acceptReleaseCatalog).not.toHaveBeenCalled();
|
|
776
|
+
expect(events).toEqual([
|
|
777
|
+
[
|
|
778
|
+
"onUpdateCheck",
|
|
779
|
+
expect.objectContaining({ status: "UNCHANGED", channel: CHANNEL }),
|
|
780
|
+
],
|
|
781
|
+
]);
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
it.each([
|
|
785
|
+
{
|
|
786
|
+
label: "an HTTP status",
|
|
787
|
+
error: () => new UpdateHttpError(503, "Service Unavailable"),
|
|
788
|
+
expected: { reason: "http", httpStatus: 503 },
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
label: "no response",
|
|
792
|
+
error: () => new TypeError("Network request failed"),
|
|
793
|
+
expected: { reason: "network" },
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
label: "a 404 without the no-catalog mark",
|
|
797
|
+
error: () => new UpdateHttpError(404, "Not Found"),
|
|
798
|
+
expected: { reason: "http", httpStatus: 404 },
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
label: "a timeout",
|
|
802
|
+
error: () => new Error("Request timed out"),
|
|
803
|
+
expected: { reason: "network", transport: "timeout" },
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
label: "an invalid catalog",
|
|
807
|
+
error: () =>
|
|
808
|
+
new InvalidUpdateResponseError("Received an invalid Release catalog"),
|
|
809
|
+
expected: { reason: "invalid_response" },
|
|
810
|
+
},
|
|
811
|
+
])("reports a check failed by $label", async ({ error, expected }) => {
|
|
812
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
813
|
+
const events = await recordPluginEvents();
|
|
814
|
+
const { client, fetchReleaseCatalog } = createClient();
|
|
815
|
+
const cause = error();
|
|
816
|
+
fetchReleaseCatalog.mockRejectedValueOnce(cause);
|
|
817
|
+
|
|
818
|
+
await expect(
|
|
819
|
+
checkForUpdate({ client, updateStrategy: "appVersion" }),
|
|
820
|
+
).resolves.toBeNull();
|
|
821
|
+
|
|
822
|
+
expect(events).toEqual([
|
|
823
|
+
[
|
|
824
|
+
"onUpdateError",
|
|
825
|
+
{
|
|
826
|
+
stage: "check",
|
|
827
|
+
resource: "catalog",
|
|
828
|
+
...expected,
|
|
829
|
+
channel: CHANNEL,
|
|
830
|
+
bundleId: CURRENT_BUNDLE_ID,
|
|
831
|
+
releaseId: null,
|
|
832
|
+
updateStrategy: "appVersion",
|
|
833
|
+
cause,
|
|
834
|
+
},
|
|
835
|
+
],
|
|
836
|
+
]);
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
it.each([
|
|
840
|
+
{
|
|
841
|
+
label: "an artifact request answered 500",
|
|
842
|
+
fail: (resolveArtifact: ReturnType<typeof vi.fn>) =>
|
|
843
|
+
resolveArtifact.mockRejectedValueOnce(
|
|
844
|
+
new UpdateHttpError(500, "Internal Server Error"),
|
|
845
|
+
),
|
|
846
|
+
expected: {
|
|
847
|
+
stage: "download",
|
|
848
|
+
reason: "http",
|
|
849
|
+
resource: "artifact",
|
|
850
|
+
httpStatus: 500,
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
label: "native extraction",
|
|
855
|
+
fail: () =>
|
|
856
|
+
mocks.stageBundle.mockRejectedValueOnce(
|
|
857
|
+
Object.assign(new Error("Failed to extract archive"), {
|
|
858
|
+
code: "UNKNOWN_ERROR",
|
|
859
|
+
userInfo: { reason: "extract", stage: "install" },
|
|
860
|
+
}),
|
|
861
|
+
),
|
|
862
|
+
expected: { stage: "install", reason: "extract" },
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
label: "a native HTTP status",
|
|
866
|
+
fail: () =>
|
|
867
|
+
mocks.stageBundle.mockRejectedValueOnce(
|
|
868
|
+
Object.assign(new Error("Failed to download bundle"), {
|
|
869
|
+
code: "DOWNLOAD_FAILED",
|
|
870
|
+
userInfo: {
|
|
871
|
+
httpStatus: 403,
|
|
872
|
+
originCode: "ExpiredToken",
|
|
873
|
+
reason: "http",
|
|
874
|
+
resource: "archive",
|
|
875
|
+
stage: "download",
|
|
876
|
+
},
|
|
877
|
+
}),
|
|
878
|
+
),
|
|
879
|
+
expected: {
|
|
880
|
+
stage: "download",
|
|
881
|
+
reason: "http",
|
|
882
|
+
resource: "archive",
|
|
883
|
+
httpStatus: 403,
|
|
884
|
+
originCode: "ExpiredToken",
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
label: "a native connection loss",
|
|
889
|
+
fail: () =>
|
|
890
|
+
mocks.stageBundle.mockRejectedValueOnce(
|
|
891
|
+
Object.assign(new Error("The network connection was lost."), {
|
|
892
|
+
code: "DOWNLOAD_FAILED",
|
|
893
|
+
userInfo: {
|
|
894
|
+
reason: "network",
|
|
895
|
+
resource: "file",
|
|
896
|
+
stage: "download",
|
|
897
|
+
transport: "connection",
|
|
898
|
+
},
|
|
899
|
+
}),
|
|
900
|
+
),
|
|
901
|
+
expected: {
|
|
902
|
+
stage: "download",
|
|
903
|
+
reason: "network",
|
|
904
|
+
resource: "file",
|
|
905
|
+
transport: "connection",
|
|
906
|
+
},
|
|
907
|
+
},
|
|
908
|
+
])(
|
|
909
|
+
"reports an install failed by $label and rethrows it",
|
|
910
|
+
async ({ fail, expected }) => {
|
|
911
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
912
|
+
const events = await recordPluginEvents();
|
|
913
|
+
const { client, resolveArtifact } = createClient();
|
|
914
|
+
fail(resolveArtifact);
|
|
915
|
+
const result = await checkForUpdate({
|
|
916
|
+
client,
|
|
917
|
+
updateStrategy: "appVersion",
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
await expect(result!.updateBundle()).rejects.toThrow();
|
|
921
|
+
|
|
922
|
+
expect(events.filter(([name]) => name === "onUpdateError")).toEqual([
|
|
923
|
+
[
|
|
924
|
+
"onUpdateError",
|
|
925
|
+
expect.objectContaining({
|
|
926
|
+
...expected,
|
|
927
|
+
channel: CHANNEL,
|
|
928
|
+
bundleId: CURRENT_BUNDLE_ID,
|
|
929
|
+
targetBundleId: TARGET_BUNDLE_ID,
|
|
930
|
+
targetReleaseId: RELEASE_ID,
|
|
931
|
+
updateStrategy: "appVersion",
|
|
932
|
+
}),
|
|
933
|
+
],
|
|
934
|
+
]);
|
|
935
|
+
},
|
|
936
|
+
);
|
|
937
|
+
|
|
938
|
+
it.each([
|
|
939
|
+
{
|
|
940
|
+
label: "a native rejection without a failure class",
|
|
941
|
+
fail: () =>
|
|
942
|
+
mocks.stageBundle.mockRejectedValueOnce(
|
|
943
|
+
Object.assign(new Error("Release catalog selection is stale"), {
|
|
944
|
+
code: "UNKNOWN_ERROR",
|
|
945
|
+
}),
|
|
946
|
+
),
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
label: "a selection that became stale",
|
|
950
|
+
fail: () => mocks.isReleaseSelectionCurrent.mockReturnValueOnce(false),
|
|
951
|
+
},
|
|
952
|
+
])("does not report $label as an update failure", async ({ fail }) => {
|
|
953
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
954
|
+
const events = await recordPluginEvents();
|
|
955
|
+
const { client } = createClient();
|
|
956
|
+
const result = await checkForUpdate({
|
|
957
|
+
client,
|
|
958
|
+
updateStrategy: "appVersion",
|
|
959
|
+
});
|
|
960
|
+
fail();
|
|
961
|
+
|
|
962
|
+
await expect(result!.updateBundle()).rejects.toThrow();
|
|
963
|
+
|
|
964
|
+
expect(events.map(([name]) => name)).toEqual(["onUpdateCheck"]);
|
|
965
|
+
});
|
|
672
966
|
});
|