@hot-updater/test-utils 1.0.0-rc.29 → 1.0.0-rc.31

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 (2) hide show
  1. package/dist/index.mjs +50 -229
  2. package/package.json +10 -10
package/dist/index.mjs CHANGED
@@ -3198,6 +3198,27 @@ const READ_BUDGETS = [
3198
3198
  },
3199
3199
  check: (count) => expect(count).toBe(11)
3200
3200
  }),
3201
+ budget({
3202
+ api: "countEventSeries: buckets in the window × shards, all used",
3203
+ read: ({ insights }) => insights.countEventSeries({
3204
+ filter: bundleEvents,
3205
+ timeRange: {
3206
+ start: T0,
3207
+ end: T0 + 3 * DAY
3208
+ },
3209
+ intervalMs: DAY
3210
+ }),
3211
+ adapter: reads(0, 0, 1, 25),
3212
+ engine: {
3213
+ calls: 1,
3214
+ rows: 6
3215
+ },
3216
+ check: (points) => expect(points.map(({ events }) => events)).toEqual([
3217
+ 24,
3218
+ 0,
3219
+ 1
3220
+ ])
3221
+ }),
3201
3222
  budget({
3202
3223
  api: "countLatestEvents: buckets in the window × shards, all used",
3203
3224
  read: ({ insights }) => insights.countLatestEvents({
@@ -3243,26 +3264,7 @@ const READ_BUDGETS = [
3243
3264
  calls: 1,
3244
3265
  rows: 1
3245
3266
  },
3246
- check: ({ data }) => expect(data[0].metrics.launches).toBe(25)
3247
- }),
3248
- budget({
3249
- api: "release activity over a window: buckets × shards, all used",
3250
- read: ({ insights }) => insights.getReleaseActivity({
3251
- scope: {
3252
- platform: "ios",
3253
- channel: "production"
3254
- },
3255
- timeRange: {
3256
- start: T0,
3257
- end: T0 + 3 * DAY
3258
- }
3259
- }),
3260
- adapter: reads(0, 0, 2, 24),
3261
- engine: {
3262
- calls: 2,
3263
- rows: 4
3264
- },
3265
- check: ({ data }) => expect(data[0].metrics.launches).toBe(25)
3267
+ check: ({ data }) => expect(data[0].metrics.applies).toBe(25)
3266
3268
  }),
3267
3269
  budget({
3268
3270
  api: "app usage: nonzero distribution and usage-sketch rows in the window, all used",
@@ -3285,27 +3287,6 @@ const READ_BUDGETS = [
3285
3287
  installations: 24
3286
3288
  }])
3287
3289
  }),
3288
- budget({
3289
- api: "daily bundle share: only scoped aggregate shards in the requested days",
3290
- read: ({ insights }) => insights.getDistributionHistory({
3291
- channel: "production",
3292
- platform: "ios",
3293
- timeRange: {
3294
- start: T0,
3295
- end: T0 + 3 * DAY
3296
- }
3297
- }),
3298
- adapter: reads(0, 0, 1, 15),
3299
- engine: {
3300
- calls: 1,
3301
- rows: 2
3302
- },
3303
- check: ({ points }) => expect(points.map(({ bundles }) => bundles.reduce((n, row) => n + row.installations, 0))).toEqual([
3304
- 24,
3305
- 0,
3306
- 1
3307
- ])
3308
- }),
3309
3290
  budget({
3310
3291
  api: "update failures of a release over a window: buckets × shards, all used",
3311
3292
  read: ({ insights }) => insights.getUpdateFailures({
@@ -3409,10 +3390,10 @@ const READ_BUDGETS = [
3409
3390
  install_id: "install-2",
3410
3391
  received_at_ms: T0 + 3 * HOUR
3411
3392
  })),
3412
- adapter: reads(5, 8, 0, 0),
3393
+ adapter: reads(4, 6, 0, 0),
3413
3394
  engine: {
3414
- calls: 3,
3415
- rows: 2
3395
+ calls: 2,
3396
+ rows: 1
3416
3397
  },
3417
3398
  writes: 1
3418
3399
  })
@@ -4434,12 +4415,13 @@ const registerInsightsModelTests = (state) => {
4434
4415
  beforeReceivedAtMs: 100
4435
4416
  })).resolves.toBe(0);
4436
4417
  });
4437
- it("maintains idempotent release, scope, usage, and latest-distribution summaries", async () => {
4418
+ it("maintains idempotent release, event series, usage, and latest-distribution summaries", async () => {
4438
4419
  const model = state.getDatabase();
4439
4420
  const releaseA = "00000000-0000-7000-8000-000000008001";
4440
4421
  const releaseB = "00000000-0000-7000-8000-000000008002";
4422
+ const base = createBundleEventRowFixture("9801", 1e3);
4441
4423
  const download = {
4442
- ...createBundleEventRowFixture("9801", 1e3),
4424
+ ...base,
4443
4425
  type: "UPDATE_DOWNLOADED",
4444
4426
  install_id: "summary-install-a",
4445
4427
  from_release_id: releaseA,
@@ -4484,57 +4466,39 @@ const registerInsightsModelTests = (state) => {
4484
4466
  const lifetime = await model.getReleaseActivity({ releases });
4485
4467
  expect(lifetime.data.map(({ metrics }) => metrics)).toEqual([{
4486
4468
  downloads: 0,
4487
- launches: 1,
4469
+ applies: 0,
4488
4470
  failedLaunches: 0
4489
4471
  }, {
4490
4472
  downloads: 1,
4491
- launches: 2,
4473
+ applies: 2,
4492
4474
  failedLaunches: 1
4493
4475
  }]);
4494
- const scope = await model.getReleaseActivity({
4495
- scope: {
4496
- platform: "ios",
4497
- channel: "production"
4498
- },
4499
- timeRange: {
4500
- start: 0,
4501
- end: 36e5
4502
- }
4503
- });
4504
- expect(scope.data[0]?.metrics).toMatchObject({
4505
- downloads: 1,
4506
- launches: 3,
4507
- failedLaunches: 1,
4508
- uniqueUsers: 2
4509
- });
4510
- const hourly = await model.getReleaseActivity({
4511
- releases: [releases[1]],
4476
+ const hourly = (filter) => model.countEventSeries({
4477
+ filter,
4512
4478
  timeRange: {
4513
4479
  start: 0,
4514
4480
  end: 108e5
4515
4481
  },
4516
4482
  intervalMs: 36e5
4517
4483
  });
4518
- expect(hourly.data[0]?.metrics.series).toEqual([
4519
- {
4520
- startMs: 0,
4521
- downloads: 1,
4522
- launches: 2,
4523
- failedLaunches: 1
4524
- },
4525
- {
4526
- startMs: 36e5,
4527
- downloads: 0,
4528
- launches: 0,
4529
- failedLaunches: 0
4530
- },
4531
- {
4532
- startMs: 72e5,
4533
- downloads: 0,
4534
- launches: 0,
4535
- failedLaunches: 0
4536
- }
4537
- ]);
4484
+ const points = (...counts) => counts.map((events, index) => ({
4485
+ startMs: index * 36e5,
4486
+ events
4487
+ }));
4488
+ const scope = {
4489
+ platform: "ios",
4490
+ channel: "production"
4491
+ };
4492
+ await expectInsightsIndex(() => hourly({
4493
+ ...scope,
4494
+ type: "UPDATE_APPLIED",
4495
+ toBundleId: base.to_bundle_id
4496
+ }), points(2, 0, 0));
4497
+ await expectInsightsIndex(() => hourly({
4498
+ ...scope,
4499
+ type: "RECOVERED",
4500
+ fromBundleId: base.from_bundle_id
4501
+ }), points(1, 0, 0));
4538
4502
  const usage = await model.getAppUsage({
4539
4503
  channel: "production",
4540
4504
  platform: "all",
@@ -4561,109 +4525,6 @@ const registerInsightsModelTests = (state) => {
4561
4525
  installations: 1
4562
4526
  }]));
4563
4527
  });
4564
- it("keeps one daily running-bundle observation through updates, recovery, retries, and later days", async () => {
4565
- const model = state.getDatabase();
4566
- const day = 864e5;
4567
- const start = Math.floor(Date.now() / day) * day - 3 * day;
4568
- const a = "00000000-0000-7000-8000-000000008001";
4569
- const b = "00000000-0000-7000-8000-000000008002";
4570
- const download = {
4571
- ...createBundleEventRowFixture("9901", start + 100),
4572
- type: "UPDATE_DOWNLOADED",
4573
- install_id: "daily-one",
4574
- from_release_id: a,
4575
- to_release_id: b
4576
- };
4577
- const applied = {
4578
- ...download,
4579
- type: "UPDATE_APPLIED",
4580
- id: createBundleEventRowFixture("9902", 0).id,
4581
- received_at_ms: start + 200
4582
- };
4583
- const read = () => model.getDistributionHistory({
4584
- platform: "ios",
4585
- channel: "production",
4586
- timeRange: {
4587
- start,
4588
- end: start + 3 * day
4589
- }
4590
- });
4591
- await record(model, download);
4592
- await expectInsightsIndex(async () => (await read()).points[0].bundles, [{
4593
- appVersion: "1.0.0",
4594
- releaseId: a,
4595
- bundleKind: "release",
4596
- installations: 1
4597
- }]);
4598
- for (const row of [
4599
- applied,
4600
- applied,
4601
- {
4602
- ...applied,
4603
- id: createBundleEventRowFixture("9903", 0).id,
4604
- install_id: "daily-two"
4605
- }
4606
- ]) await record(model, row);
4607
- const recovered = {
4608
- ...applied,
4609
- id: createBundleEventRowFixture("9904", 0).id,
4610
- type: "RECOVERED",
4611
- from_release_id: b,
4612
- to_release_id: a,
4613
- received_at_ms: start + 300
4614
- };
4615
- await record(model, recovered);
4616
- await record(model, {
4617
- ...applied,
4618
- id: createBundleEventRowFixture("9905", 0).id,
4619
- received_at_ms: start + day + 100
4620
- });
4621
- await record(model, {
4622
- ...applied,
4623
- id: createBundleEventRowFixture("9906", 0).id,
4624
- received_at_ms: start + 250
4625
- });
4626
- await record(model, {
4627
- ...applied,
4628
- id: createBundleEventRowFixture("9907", 0).id,
4629
- install_id: "other-scope",
4630
- channel: "preview"
4631
- });
4632
- await expectInsightsIndex(async () => {
4633
- return (await read()).points.map((point) => ({
4634
- ...point,
4635
- bundles: [...point.bundles].sort((x, y) => (x.releaseId ?? "").localeCompare(y.releaseId ?? ""))
4636
- }));
4637
- }, [
4638
- {
4639
- startMs: start,
4640
- bundles: [{
4641
- appVersion: "1.0.0",
4642
- releaseId: a,
4643
- bundleKind: "release",
4644
- installations: 1
4645
- }, {
4646
- appVersion: "1.0.0",
4647
- releaseId: b,
4648
- bundleKind: "release",
4649
- installations: 1
4650
- }]
4651
- },
4652
- {
4653
- startMs: start + day,
4654
- bundles: [{
4655
- appVersion: "1.0.0",
4656
- releaseId: b,
4657
- bundleKind: "release",
4658
- installations: 1
4659
- }]
4660
- },
4661
- {
4662
- startMs: start + 2 * day,
4663
- bundles: []
4664
- }
4665
- ]);
4666
- });
4667
4528
  it("pages insights events newest first with a stable cursor", async () => {
4668
4529
  const model = state.getDatabase();
4669
4530
  const first = createBundleEventRowFixture("701", 100);
@@ -4865,46 +4726,6 @@ const setupInsightsHttpTestSuite = (options) => {
4865
4726
  return (await (await client.admin(`/overview?platform=ios&channel=${encodeURIComponent(channel)}&window=24h`)).json()).reportingInstallations.count;
4866
4727
  }, 1);
4867
4728
  });
4868
- it("serves daily observed bundles through the authenticated admin API", async () => {
4869
- const client = options.getClient();
4870
- const channel = `share-${crypto.randomUUID()}`;
4871
- const day = 864e5;
4872
- const start = Math.floor(Date.now() / day) * day;
4873
- const event = {
4874
- appVersion: "1.0.0",
4875
- channel,
4876
- cohort: "default",
4877
- fingerprintHash: null,
4878
- fromBundleId: null,
4879
- fromReleaseId: null,
4880
- installId: `share-${crypto.randomUUID()}`,
4881
- platform: "ios",
4882
- toBundleId: "00000000-0000-0000-0000-000000000000",
4883
- toReleaseId: null,
4884
- type: "UNCHANGED",
4885
- updateStrategy: null
4886
- };
4887
- const reported = await client.client("/events", jsonRequest$1("POST", event));
4888
- expect(reported.status).toBe(204);
4889
- await reported.text();
4890
- const path = `/distribution-history?platform=ios&channel=${channel}&start=${start}&end=${start + day}`;
4891
- await expectInsightsIndex(async () => {
4892
- const response = await client.admin(path);
4893
- expect(response.status).toBe(200);
4894
- return (await response.json()).points;
4895
- }, [{
4896
- startMs: start,
4897
- bundles: [{
4898
- appVersion: "1.0.0",
4899
- releaseId: null,
4900
- bundleKind: "builtin",
4901
- installations: 1
4902
- }]
4903
- }]);
4904
- const invalid = await client.admin(`/distribution-history?platform=ios&channel=${channel}&start=${start}&end=${start + 40 * day}`);
4905
- expect(invalid.status).toBe(400);
4906
- await invalid.text();
4907
- });
4908
4729
  it.each([
4909
4730
  {
4910
4731
  type: "UNCHANGED",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/test-utils",
3
- "version": "1.0.0-rc.29",
3
+ "version": "1.0.0-rc.31",
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.30",
54
- "@hot-updater/server": "^1.0.0-rc.30",
55
- "@hot-updater/protocol": "^1.0.0-rc.28",
56
- "@hot-updater/plugin-core": "^1.0.0-rc.28"
53
+ "@hot-updater/plugin-insights": "^1.0.0-rc.33",
54
+ "@hot-updater/server": "^1.0.0-rc.33",
55
+ "@hot-updater/protocol": "^1.0.0-rc.29",
56
+ "@hot-updater/plugin-core": "^1.0.0-rc.29"
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.30",
87
- "@hot-updater/js": "1.0.0-rc.27",
88
- "@hot-updater/protocol": "1.0.0-rc.28",
89
- "@hot-updater/plugin-core": "1.0.0-rc.28",
90
- "@hot-updater/server": "1.0.0-rc.30"
86
+ "@hot-updater/plugin-insights": "1.0.0-rc.33",
87
+ "@hot-updater/protocol": "1.0.0-rc.29",
88
+ "@hot-updater/plugin-core": "1.0.0-rc.29",
89
+ "@hot-updater/server": "1.0.0-rc.33",
90
+ "@hot-updater/js": "1.0.0-rc.27"
91
91
  },
92
92
  "inlinedDependencies": {
93
93
  "@nodelib/fs.scandir": "2.1.5",