All files / lib/checkout stripe-mock.ts

100% Statements 13/13
100% Branches 8/8
100% Functions 5/5
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70                                                      2x 2x   2x 24x     2x       2x 2x                         2x   2x 2x 2x   2x                      
import type { CartLineItem } from "@/lib/cart/cart-types";
import { withBasePath } from "@/lib/routing";
 
export type MockCheckoutStatus = "failure" | "success";
 
/**
 * Input shape for browser-only Stripe Checkout session simulation.
 */
export interface MockCheckoutInput {
  readonly forceResult?: MockCheckoutStatus;
  readonly items: readonly CartLineItem[];
  readonly latencyMs?: number;
  readonly subtotalCents: number;
}
 
/**
 * Mock session returned to the checkout UI without contacting Stripe.
 */
export interface MockCheckoutSession {
  readonly amountTotalCents: number;
  readonly checkoutUrl: string;
  readonly message: string;
  readonly sessionId: string;
  readonly status: MockCheckoutStatus;
}
 
function createStableSessionId(items: readonly CartLineItem[], subtotalCents: number): string {
  const seed = items.map((item) => `${item.product.slug}:${item.quantity}`).join("|");
  let hash = subtotalCents;
 
  for (const character of seed) {
    hash = (hash * 31 + character.charCodeAt(0)) % 1_000_000_007;
  }
 
  return `cs_mock_${hash.toString(36)}`;
}
 
function wait(ms: number): Promise<void> {
  return new Promise((resolve) => {
    window.setTimeout(resolve, ms);
  });
}
 
/**
 * Simulates Stripe Checkout session creation entirely in the browser.
 */
export async function createMockStripeCheckoutSession({
  forceResult,
  items,
  latencyMs = 350,
  subtotalCents,
}: MockCheckoutInput): Promise<MockCheckoutSession> {
  await wait(latencyMs);
 
  const shouldFail = forceResult === "failure" || items.length === 0 || subtotalCents <= 0;
  const status: MockCheckoutStatus = shouldFail ? "failure" : "success";
  const sessionId = createStableSessionId(items, subtotalCents);
 
  return {
    amountTotalCents: subtotalCents,
    checkoutUrl: `${withBasePath("/checkout/")}?session_id=${sessionId}&mock=stripe`,
    message:
      status === "success"
        ? "Sessione Stripe mock creata. Nessuna chiave reale e nessun pagamento inviato."
        : "Sessione mock non creata: controlla il carrello e riprova.",
    sessionId,
    status,
  };
}