@hot-updater/test-utils 1.0.0-rc.40 → 1.0.0-rc.41
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/dist/index.mjs +61 -2
- package/dist/react-native.cjs +12 -3
- package/dist/react-native.d.cts +12 -5
- package/dist/react-native.d.mts +12 -5
- package/dist/react-native.mjs +12 -3
- package/package.json +10 -10
package/dist/index.mjs
CHANGED
|
@@ -2797,6 +2797,21 @@ const createMeasuredDatabase = async (adapter, plugins, options = {}) => {
|
|
|
2797
2797
|
};
|
|
2798
2798
|
//#endregion
|
|
2799
2799
|
//#region src/setupReadBudgetTestSuite.ts
|
|
2800
|
+
/** A published template: a greeting that beta devices get another value of. */
|
|
2801
|
+
const remoteConfigTemplate = (greeting) => ({
|
|
2802
|
+
conditions: [{
|
|
2803
|
+
name: "Beta",
|
|
2804
|
+
rules: [{
|
|
2805
|
+
type: "channel",
|
|
2806
|
+
channels: ["beta"]
|
|
2807
|
+
}]
|
|
2808
|
+
}],
|
|
2809
|
+
parameters: { greeting: {
|
|
2810
|
+
valueType: "STRING",
|
|
2811
|
+
defaultValue: { value: greeting },
|
|
2812
|
+
conditionalValues: { Beta: { value: `${greeting}, tester` } }
|
|
2813
|
+
} }
|
|
2814
|
+
});
|
|
2800
2815
|
const DAY = 864e5;
|
|
2801
2816
|
const HOUR = 36e5;
|
|
2802
2817
|
/** The UTC midnight Insights events start at. */
|
|
@@ -2967,11 +2982,20 @@ const seed = async (database) => {
|
|
|
2967
2982
|
await api.insights.recordEvent(failureOf(1, 3));
|
|
2968
2983
|
await api.insights.recordEvent(failureOf(2, 5));
|
|
2969
2984
|
await api.insights.recordEvent(failureOf(3, 7, true));
|
|
2985
|
+
for (const [baseVersion, greeting] of [
|
|
2986
|
+
"Hi",
|
|
2987
|
+
"Hello",
|
|
2988
|
+
"Hey"
|
|
2989
|
+
].entries()) await api.remoteConfig.publish({
|
|
2990
|
+
template: remoteConfigTemplate(greeting),
|
|
2991
|
+
baseVersion
|
|
2992
|
+
});
|
|
2970
2993
|
const channel = (name) => core.findChannelByName(name).then((found) => found);
|
|
2971
2994
|
const productionId = (await channel("production")).id;
|
|
2972
2995
|
return {
|
|
2973
2996
|
core,
|
|
2974
2997
|
insights: api.insights,
|
|
2998
|
+
remoteConfig: api.remoteConfig,
|
|
2975
2999
|
clientAuth: database.clientAuth,
|
|
2976
3000
|
apiKey,
|
|
2977
3001
|
productionId,
|
|
@@ -3024,6 +3048,33 @@ const READ_BUDGETS = [
|
|
|
3024
3048
|
},
|
|
3025
3049
|
check: (catalog) => expect(catalog?.releases).toHaveLength(4)
|
|
3026
3050
|
}),
|
|
3051
|
+
budget({
|
|
3052
|
+
api: "remote config fetch: 1 point read of the active template",
|
|
3053
|
+
read: ({ remoteConfig }) => remoteConfig.resolve({
|
|
3054
|
+
platform: "ios",
|
|
3055
|
+
channel: "beta"
|
|
3056
|
+
}),
|
|
3057
|
+
adapter: reads(1, 1, 0, 0),
|
|
3058
|
+
engine: {
|
|
3059
|
+
calls: 1,
|
|
3060
|
+
rows: 1
|
|
3061
|
+
},
|
|
3062
|
+
check: (resolved) => expect(resolved).toEqual({
|
|
3063
|
+
version: 3,
|
|
3064
|
+
values: { greeting: "Hey, tester" }
|
|
3065
|
+
})
|
|
3066
|
+
}),
|
|
3067
|
+
budget({
|
|
3068
|
+
api: "remote config versions page: limit rows from one query",
|
|
3069
|
+
read: ({ remoteConfig }) => remoteConfig.listVersions({ limit: 2 }),
|
|
3070
|
+
adapter: reads(0, 0, 1, 2),
|
|
3071
|
+
engine: {
|
|
3072
|
+
calls: 1,
|
|
3073
|
+
rows: 2
|
|
3074
|
+
},
|
|
3075
|
+
returned: (page) => page.versions.length,
|
|
3076
|
+
check: (page) => expect(page.versions.map(({ version }) => version)).toEqual([3, 2])
|
|
3077
|
+
}),
|
|
3027
3078
|
budget({
|
|
3028
3079
|
api: "artifact resolution: 1 batch get of 2 bundles and 1 unique patch read",
|
|
3029
3080
|
read: ({ core }) => core.getArtifactInfo(createBundleFixture("106").id, createBundleFixture("105").id, 1),
|
|
@@ -3428,8 +3479,16 @@ const setupReadBudgetTestSuite = (options) => {
|
|
|
3428
3479
|
let seeded;
|
|
3429
3480
|
let writes = 0;
|
|
3430
3481
|
beforeAll(async () => {
|
|
3431
|
-
const [{ insights }, { apiKeys }] = await Promise.all([
|
|
3432
|
-
|
|
3482
|
+
const [{ insights }, { apiKeys }, { remoteConfig }] = await Promise.all([
|
|
3483
|
+
import("@hot-updater/server/plugins/insights"),
|
|
3484
|
+
import("@hot-updater/server/plugins/api-keys"),
|
|
3485
|
+
import("@hot-updater/server/plugins/remote-config")
|
|
3486
|
+
]);
|
|
3487
|
+
const plugins = [
|
|
3488
|
+
insights(),
|
|
3489
|
+
apiKeys(),
|
|
3490
|
+
remoteConfig()
|
|
3491
|
+
];
|
|
3433
3492
|
created = await options.createAdapter({
|
|
3434
3493
|
tables: [...toolingTargetOf(plugins).schema.tables, SETTINGS_TABLE],
|
|
3435
3494
|
nativePageSize: NATIVE_PAGE_SIZE
|
package/dist/react-native.cjs
CHANGED
|
@@ -12,6 +12,7 @@ let _hot_updater_protocol = require("@hot-updater/protocol");
|
|
|
12
12
|
* runtime.hooks.onAppReady(launch);
|
|
13
13
|
* await runtime.settled();
|
|
14
14
|
* expect(runtime.requests[0]?.json()).toEqual(expectedEvent);
|
|
15
|
+
* runtime.api.someMethod(); // the API the plugin adds as hotUpdater.<id>
|
|
15
16
|
* ```
|
|
16
17
|
*
|
|
17
18
|
* It sets plugins up with the plugin host from `@hot-updater/protocol`,
|
|
@@ -139,7 +140,7 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
139
140
|
},
|
|
140
141
|
now: () => options.now ? options.now() : Date.now()
|
|
141
142
|
});
|
|
142
|
-
host.configurePlugins(plugins, {
|
|
143
|
+
const apis = host.configurePlugins(plugins, {
|
|
143
144
|
baseURL,
|
|
144
145
|
requestHeaders: options.requestHeaders,
|
|
145
146
|
requestTimeout: options.requestTimeout,
|
|
@@ -151,6 +152,7 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
151
152
|
for (const settlement of host.dispatchPluginHook(name, payload)) track(settlement);
|
|
152
153
|
};
|
|
153
154
|
return {
|
|
155
|
+
apis,
|
|
154
156
|
hooks: {
|
|
155
157
|
onAppReady: call("onAppReady"),
|
|
156
158
|
onUpdateCheck: call("onUpdateCheck"),
|
|
@@ -171,8 +173,15 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
171
173
|
}
|
|
172
174
|
};
|
|
173
175
|
};
|
|
174
|
-
/** Sets one plugin up; see `setupClientPlugins`. */
|
|
175
|
-
const setupClientPlugin = (plugin, options) =>
|
|
176
|
+
/** Sets one plugin up; see `setupClientPlugins`. `api` is the plugin's API. */
|
|
177
|
+
const setupClientPlugin = (plugin, options) => {
|
|
178
|
+
const runtime = setupClientPlugins([plugin], options);
|
|
179
|
+
const apis = runtime.apis;
|
|
180
|
+
return {
|
|
181
|
+
...runtime,
|
|
182
|
+
api: apis[plugin.id]
|
|
183
|
+
};
|
|
184
|
+
};
|
|
176
185
|
//#endregion
|
|
177
186
|
exports.createTestStorage = createTestStorage;
|
|
178
187
|
exports.setupClientPlugin = setupClientPlugin;
|
package/dist/react-native.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppReadyResult, BundleDownloadedInfo, HotUpdaterBaseURL, HotUpdaterClientPlugin, UpdateCheckResult, UpdateError, UpdateHttpResponse } from "@hot-updater/protocol";
|
|
1
|
+
import { AppReadyResult, BundleDownloadedInfo, ClientPluginApi, ClientPluginApis, HotUpdaterBaseURL, HotUpdaterClientPlugin, UpdateCheckResult, UpdateError, UpdateHttpResponse } from "@hot-updater/protocol";
|
|
2
2
|
//#region src/setupClientPlugins.d.ts
|
|
3
3
|
/** A value the test fixes, or reads each time a plugin asks for it. */
|
|
4
4
|
type TestValue<T> = T | (() => T);
|
|
@@ -77,7 +77,12 @@ interface ClientPluginTestHooks {
|
|
|
77
77
|
onHttpResponse(response: UpdateHttpResponse): void;
|
|
78
78
|
}
|
|
79
79
|
/** One JavaScript runtime with the plugins set up, as after `HotUpdater.init`. */
|
|
80
|
-
interface ClientPluginTestRuntime {
|
|
80
|
+
interface ClientPluginTestRuntime<TApis = Readonly<Record<string, unknown>>> {
|
|
81
|
+
/**
|
|
82
|
+
* The plugins' APIs by plugin id, as the instance `HotUpdater.init`
|
|
83
|
+
* returns has them.
|
|
84
|
+
*/
|
|
85
|
+
readonly apis: TApis;
|
|
81
86
|
/**
|
|
82
87
|
* Calls a hook on every plugin that returned it, as the SDK does: without
|
|
83
88
|
* waiting for it, and with a throw or rejection recorded in `errors`
|
|
@@ -104,8 +109,10 @@ interface ClientPluginTestRuntime {
|
|
|
104
109
|
/** A new device's empty plugin storage. */
|
|
105
110
|
declare const createTestStorage: () => ClientPluginTestStorage;
|
|
106
111
|
/** Sets plugins up as `HotUpdater.init({ plugins })` does, in a new runtime. */
|
|
107
|
-
declare const setupClientPlugins:
|
|
108
|
-
/** Sets one plugin up; see `setupClientPlugins`. */
|
|
109
|
-
declare const setupClientPlugin: (plugin:
|
|
112
|
+
declare const setupClientPlugins: <const TPlugins extends readonly HotUpdaterClientPlugin[]>(plugins: TPlugins, options?: ClientPluginTestOptions) => ClientPluginTestRuntime<ClientPluginApis<TPlugins>>;
|
|
113
|
+
/** Sets one plugin up; see `setupClientPlugins`. `api` is the plugin's API. */
|
|
114
|
+
declare const setupClientPlugin: <const P extends HotUpdaterClientPlugin>(plugin: P, options?: ClientPluginTestOptions) => ClientPluginTestRuntime<ClientPluginApis<readonly [P]>> & {
|
|
115
|
+
readonly api: ClientPluginApi<P>;
|
|
116
|
+
};
|
|
110
117
|
//#endregion
|
|
111
118
|
export { ClientPluginTestHooks, ClientPluginTestOptions, ClientPluginTestRequest, ClientPluginTestRuntime, ClientPluginTestStorage, createTestStorage, setupClientPlugin, setupClientPlugins };
|
package/dist/react-native.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppReadyResult, BundleDownloadedInfo, HotUpdaterBaseURL, HotUpdaterClientPlugin, UpdateCheckResult, UpdateError, UpdateHttpResponse } from "@hot-updater/protocol";
|
|
1
|
+
import { AppReadyResult, BundleDownloadedInfo, ClientPluginApi, ClientPluginApis, HotUpdaterBaseURL, HotUpdaterClientPlugin, UpdateCheckResult, UpdateError, UpdateHttpResponse } from "@hot-updater/protocol";
|
|
2
2
|
//#region src/setupClientPlugins.d.ts
|
|
3
3
|
/** A value the test fixes, or reads each time a plugin asks for it. */
|
|
4
4
|
type TestValue<T> = T | (() => T);
|
|
@@ -77,7 +77,12 @@ interface ClientPluginTestHooks {
|
|
|
77
77
|
onHttpResponse(response: UpdateHttpResponse): void;
|
|
78
78
|
}
|
|
79
79
|
/** One JavaScript runtime with the plugins set up, as after `HotUpdater.init`. */
|
|
80
|
-
interface ClientPluginTestRuntime {
|
|
80
|
+
interface ClientPluginTestRuntime<TApis = Readonly<Record<string, unknown>>> {
|
|
81
|
+
/**
|
|
82
|
+
* The plugins' APIs by plugin id, as the instance `HotUpdater.init`
|
|
83
|
+
* returns has them.
|
|
84
|
+
*/
|
|
85
|
+
readonly apis: TApis;
|
|
81
86
|
/**
|
|
82
87
|
* Calls a hook on every plugin that returned it, as the SDK does: without
|
|
83
88
|
* waiting for it, and with a throw or rejection recorded in `errors`
|
|
@@ -104,8 +109,10 @@ interface ClientPluginTestRuntime {
|
|
|
104
109
|
/** A new device's empty plugin storage. */
|
|
105
110
|
declare const createTestStorage: () => ClientPluginTestStorage;
|
|
106
111
|
/** Sets plugins up as `HotUpdater.init({ plugins })` does, in a new runtime. */
|
|
107
|
-
declare const setupClientPlugins:
|
|
108
|
-
/** Sets one plugin up; see `setupClientPlugins`. */
|
|
109
|
-
declare const setupClientPlugin: (plugin:
|
|
112
|
+
declare const setupClientPlugins: <const TPlugins extends readonly HotUpdaterClientPlugin[]>(plugins: TPlugins, options?: ClientPluginTestOptions) => ClientPluginTestRuntime<ClientPluginApis<TPlugins>>;
|
|
113
|
+
/** Sets one plugin up; see `setupClientPlugins`. `api` is the plugin's API. */
|
|
114
|
+
declare const setupClientPlugin: <const P extends HotUpdaterClientPlugin>(plugin: P, options?: ClientPluginTestOptions) => ClientPluginTestRuntime<ClientPluginApis<readonly [P]>> & {
|
|
115
|
+
readonly api: ClientPluginApi<P>;
|
|
116
|
+
};
|
|
110
117
|
//#endregion
|
|
111
118
|
export { ClientPluginTestHooks, ClientPluginTestOptions, ClientPluginTestRequest, ClientPluginTestRuntime, ClientPluginTestStorage, createTestStorage, setupClientPlugin, setupClientPlugins };
|
package/dist/react-native.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { createPluginHost, pluginStorageKey, resolveBaseURL } from "@hot-updater
|
|
|
11
11
|
* runtime.hooks.onAppReady(launch);
|
|
12
12
|
* await runtime.settled();
|
|
13
13
|
* expect(runtime.requests[0]?.json()).toEqual(expectedEvent);
|
|
14
|
+
* runtime.api.someMethod(); // the API the plugin adds as hotUpdater.<id>
|
|
14
15
|
* ```
|
|
15
16
|
*
|
|
16
17
|
* It sets plugins up with the plugin host from `@hot-updater/protocol`,
|
|
@@ -138,7 +139,7 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
138
139
|
},
|
|
139
140
|
now: () => options.now ? options.now() : Date.now()
|
|
140
141
|
});
|
|
141
|
-
host.configurePlugins(plugins, {
|
|
142
|
+
const apis = host.configurePlugins(plugins, {
|
|
142
143
|
baseURL,
|
|
143
144
|
requestHeaders: options.requestHeaders,
|
|
144
145
|
requestTimeout: options.requestTimeout,
|
|
@@ -150,6 +151,7 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
150
151
|
for (const settlement of host.dispatchPluginHook(name, payload)) track(settlement);
|
|
151
152
|
};
|
|
152
153
|
return {
|
|
154
|
+
apis,
|
|
153
155
|
hooks: {
|
|
154
156
|
onAppReady: call("onAppReady"),
|
|
155
157
|
onUpdateCheck: call("onUpdateCheck"),
|
|
@@ -170,7 +172,14 @@ const setupClientPlugins = (plugins, options = {}) => {
|
|
|
170
172
|
}
|
|
171
173
|
};
|
|
172
174
|
};
|
|
173
|
-
/** Sets one plugin up; see `setupClientPlugins`. */
|
|
174
|
-
const setupClientPlugin = (plugin, options) =>
|
|
175
|
+
/** Sets one plugin up; see `setupClientPlugins`. `api` is the plugin's API. */
|
|
176
|
+
const setupClientPlugin = (plugin, options) => {
|
|
177
|
+
const runtime = setupClientPlugins([plugin], options);
|
|
178
|
+
const apis = runtime.apis;
|
|
179
|
+
return {
|
|
180
|
+
...runtime,
|
|
181
|
+
api: apis[plugin.id]
|
|
182
|
+
};
|
|
183
|
+
};
|
|
175
184
|
//#endregion
|
|
176
185
|
export { createTestStorage, setupClientPlugin, setupClientPlugins };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/test-utils",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.41",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Test utilities for Hot Updater packages",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"mysql2": "*",
|
|
51
51
|
"pg": "*",
|
|
52
52
|
"vitest": "^4.0.0",
|
|
53
|
-
"@hot-updater/plugin-insights": "^1.0.0-rc.
|
|
54
|
-
"@hot-updater/protocol": "^1.0.0-rc.
|
|
55
|
-
"@hot-updater/plugin-core": "^1.0.0-rc.
|
|
56
|
-
"@hot-updater/server": "^1.0.0-rc.
|
|
53
|
+
"@hot-updater/plugin-insights": "^1.0.0-rc.41",
|
|
54
|
+
"@hot-updater/protocol": "^1.0.0-rc.41",
|
|
55
|
+
"@hot-updater/plugin-core": "^1.0.0-rc.41",
|
|
56
|
+
"@hot-updater/server": "^1.0.0-rc.41"
|
|
57
57
|
},
|
|
58
58
|
"peerDependenciesMeta": {
|
|
59
59
|
"@electric-sql/pglite": {
|
|
@@ -83,11 +83,11 @@
|
|
|
83
83
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
84
84
|
"vitest": "4.1.4",
|
|
85
85
|
"workspace-tools": "^0.41.7",
|
|
86
|
-
"@hot-updater/plugin-insights": "1.0.0-rc.
|
|
87
|
-
"@hot-updater/protocol": "1.0.0-rc.
|
|
88
|
-
"@hot-updater/js": "1.0.0-rc.
|
|
89
|
-
"@hot-updater/plugin-core": "1.0.0-rc.
|
|
90
|
-
"@hot-updater/server": "1.0.0-rc.
|
|
86
|
+
"@hot-updater/plugin-insights": "1.0.0-rc.41",
|
|
87
|
+
"@hot-updater/protocol": "1.0.0-rc.41",
|
|
88
|
+
"@hot-updater/js": "1.0.0-rc.41",
|
|
89
|
+
"@hot-updater/plugin-core": "1.0.0-rc.41",
|
|
90
|
+
"@hot-updater/server": "1.0.0-rc.41"
|
|
91
91
|
},
|
|
92
92
|
"inlinedDependencies": {
|
|
93
93
|
"@nodelib/fs.scandir": "2.1.5",
|