160 lines · 7.8 KB
import { beforeEach, describe, expect, test } from "bun:test";
import type Stripe from "stripe";
const { state, disabled, adminNotices, processStripeEvent, event, post, plan, subscription, resetWebhookHarness } =
  await import("./webhook.test-helper");

beforeEach(() => resetWebhookHarness());

describe("release hardening", () => {
  const invoice = (subscriptionId: string) => ({
    customer: "cus_1",
    parent: { subscription_details: { subscription: subscriptionId } },
  });
  const status = () =>
    (
      state.d1.db.query("SELECT subscription_status AS s FROM billing_customers WHERE account_id = 'o1'").get() as {
        s: string;
      }
    ).s;

  test("events from the other Stripe mode are ignored", async () => {
    const live = { ...event("customer.subscription.created", subscription("active")), livemode: true };
    expect(await processStripeEvent(live as Stripe.Event)).toBe("ignored");
    expect(plan("o1")).toBeNull();
    expect((await post(live as Stripe.Event)).status).toBe(200);
    expect(plan("o1")).toBeNull();
  });

  test("invoice.paid recovers a past_due subscription; an older one cannot", async () => {
    await processStripeEvent(event("customer.subscription.created", subscription("active"), 100));
    await processStripeEvent(event("invoice.payment_failed", invoice("sub_1"), 200));
    expect(status()).toBe("past_due");
    await processStripeEvent(event("invoice.paid", invoice("sub_other"), 300));
    expect(status()).toBe("past_due");
    await processStripeEvent(event("invoice.paid", invoice("sub_1"), 50));
    expect(status()).toBe("past_due");
    expect(await processStripeEvent(event("invoice.paid", invoice("sub_1"), 300))).toBe("processed");
    expect(status()).toBe("active");
    expect(plan("o1")).toBe("pro");
  });