From 38d829597a153fa3b9397b52573f20727bd601ca Mon Sep 17 00:00:00 2001 From: yusufipk Date: Thu, 30 Jul 2026 19:30:34 +0700 Subject: [PATCH] test(api): pin the stripe-disabled guard to a real empty result The guard is `{ id: { in: [] } }`, which is only safe because Prisma renders an empty IN list as `WHERE 1=0` instead of dropping the filter. A regression there would delete every workspace on a self-hosted deployment, which is too expensive to leave resting on that assumption. --- tests/api/expired-billing-cleanup.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/api/expired-billing-cleanup.test.ts b/tests/api/expired-billing-cleanup.test.ts index af72720..01d1989 100644 --- a/tests/api/expired-billing-cleanup.test.ts +++ b/tests/api/expired-billing-cleanup.test.ts @@ -121,6 +121,21 @@ describe('cleanupExpiredBillingWorkspaces', () => { expect(bunnyDeletes).toEqual([]); }); + // The guard is `{ id: { in: [] } }`, and an empty IN list is only safe if Prisma renders it + // as a contradiction rather than dropping the filter. It renders `WHERE 1=0`, but a + // regression there would delete every workspace on a self-hosted deployment, so it is worth + // a test rather than trust. + it('deletes nothing when Stripe is disabled, since nothing can expire without billing', async () => { + vi.stubEnv('OPENFRAME_ENABLE_STRIPE', 'false'); + const { workspace } = await seedCanceledOwner(30); + + const result = await cleanupExpiredBillingWorkspaces(); + + expect(result).toEqual({ owners: 0, scanned: 0, deleted: 0 }); + expect(await db.workspace.findUnique({ where: { id: workspace.id } })).not.toBeNull(); + expect(bunnyDeletes).toEqual([]); + }); + it('counts an expired owner who owns no workspace, so an empty scan is not mistaken for an empty user table', async () => { await createUser({ subscriptionStatus: BillingSubscriptionStatus.CANCELED,