test(integrations): align status tests with dropped legacy counter + lock in down-script recipe

Five test surfaces updated to match the v1.4.47 W1 drop:

  - `src/lib/integrations/__tests__/status.test.ts`
    * `recordSyncSuccess`, `markDisconnected`, `markReconnected`,
      `resumeIntegrationFromPark` upsert assertions drop the
      `consecutiveFailures: 0` field.
    * Alert-ladder tests now seed the existing-row mock with a bucket
      payload at N-1 so the in-memory increment lands at N — the
      writer no longer consults the upsert return's
      `consecutiveFailures` for the threshold check.
    * The "back-fills from legacy single counter" case is replaced
      with a "seeds a fresh zero envelope when the row has no bucket
      payload yet" case (the back-fill path is gone).
    * New `down-script restores legacy consecutiveFailures via
      Math.max` block locks in the migration 0076 rollback recipe at
      the JS level: an in-memory `projectLegacyCounter` mirrors the
      SQL `GREATEST(transient, reauth_required, persistent)`
      projection and is asserted against zero, null, the 28-deep
      production-shape persistent streak, and parity with the live
      alert ladder's `Math.max(...Object.values(buckets))`.
    * Stale `consecutiveFailures: N` properties on Prisma mock returns
      are stripped (the writer no longer reads them).

  - `src/lib/integrations/__tests__/admin-alert.test.ts`
    * `parkIntegrationAtReauth` "creates a fresh row at counter=0"
      now asserts the zero bucket envelope rather than the dropped
      `consecutiveFailures: 0` literal.
    * The "not.toHaveProperty consecutiveFailures" assertion gains
      a sibling for `consecutiveFailuresByKind` — the bucket is the
      live counter now, and `parkIntegrationAtReauth` must still leave
      it untouched on a re-park.

  - `src/components/settings/__tests__/integrations-section.test.tsx`
    * The six fixture envelopes drop the now-removed
      `consecutiveFailures: N` field (the view-model dropped the
      property in this release).

  - `tests/integration/integration-status.test.ts`
    * Five `row.consecutiveFailures` assertions are migrated to
      `row.consecutiveFailuresByKind` matchers carrying the same
      counter value bucketed by failure kind.
    * The parked-state fixture's `integrationStatus.create` call no
      longer sets the dropped column.
This commit is contained in:
Marc-André Bombeck committed 2026-05-22 09:16:30 +02:00
1 parent 0cdf974e07
commit 76e62283fa
4 files changed
+211 -66

No files matched your search

+24 -6
View File
@@ -84,7 +84,13 @@ describe("IntegrationStatus end-to-end", () => {
});
expect(status).not.toBeNull();
expect(status!.state).toBe("error_transient");
expect(status!.consecutiveFailures).toBe(1);
// v1.4.47 W1 — legacy `consecutiveFailures` column dropped; the
// per-kind bucket is now the sole counter.
expect(status!.consecutiveFailuresByKind).toMatchObject({
transient: 1,
reauth_required: 0,
persistent: 0,
});
expect(status!.lastAttemptAt).toBeInstanceOf(Date);
expect(status!.lastError).toBeTruthy();
// Encrypted at rest — must NOT be the plaintext message.
@@ -116,7 +122,13 @@ describe("IntegrationStatus end-to-end", () => {
const snapshot = await getIntegrationStatus(TEST_USER_ID, "moodlog");
expect(snapshot.state).toBe("error_transient");
expect(snapshot.lastError).toBe("moodLog sync HTTP 502");
expect(snapshot.consecutiveFailures).toBe(1);
// v1.4.47 W1 — snapshot drops the legacy `consecutiveFailures`
// scalar; the per-kind bucket carries the count.
expect(snapshot.consecutiveFailuresByKind).toMatchObject({
transient: 1,
reauth_required: 0,
persistent: 0,
});
});
it("recordSyncSuccess clears the streak, resets state, and (importantly) does NOT write an audit row", async () => {
@@ -134,7 +146,11 @@ describe("IntegrationStatus end-to-end", () => {
},
});
expect(status!.state).toBe("connected");
expect(status!.consecutiveFailures).toBe(0);
expect(status!.consecutiveFailuresByKind).toMatchObject({
transient: 0,
reauth_required: 0,
persistent: 0,
});
expect(status!.lastError).toBeNull();
expect(status!.lastSuccessAt).toBeInstanceOf(Date);
@@ -242,7 +258,11 @@ describe("IntegrationStatus end-to-end", () => {
});
expect(row!.state).toBe("disconnected");
expect(row!.lastError).toBeNull();
expect(row!.consecutiveFailures).toBe(0);
expect(row!.consecutiveFailuresByKind).toMatchObject({
transient: 0,
reauth_required: 0,
persistent: 0,
});
});
// v1.4.43 W14 — end-to-end resume flow against real Postgres.
@@ -259,7 +279,6 @@ describe("IntegrationStatus end-to-end", () => {
userId: TEST_USER_ID,
integration: "withings",
state: "parked",
consecutiveFailures: 30,
consecutiveFailuresByKind: {
transient: 2,
reauth_required: 0,
@@ -286,7 +305,6 @@ describe("IntegrationStatus end-to-end", () => {
});
expect(row).not.toBeNull();
expect(row!.state).toBe("connected");
expect(row!.consecutiveFailures).toBe(0);
expect(row!.consecutiveFailuresByKind).toEqual({
transient: 0,
reauth_required: 0,