fix stripe removal tests
Build & Push / Pipeline Tests (push) Failing after 1m26s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 49s
Test / API Unit Tests (push) Failing after 1m8s
Test / Homepage Unit Tests (push) Successful in 44s
Test / Carplace Unit Tests (push) Successful in 42s
Test / Admin Unit Tests (push) Successful in 39s
Test / Dashboard Unit Tests (push) Successful in 45s
Test / API Integration Tests (push) Failing after 1m7s

This commit is contained in:
root
2026-08-17 21:15:35 -04:00
parent fe8ffbeb9f
commit 653074be3e
9 changed files with 15 additions and 142 deletions
@@ -38,7 +38,7 @@ describe('operational schemas', () => {
plan: 'PRO', plan: 'PRO',
billingPeriod: 'MONTHLY', billingPeriod: 'MONTHLY',
currency: 'MAD', currency: 'MAD',
method: 'STRIPE', method: 'CASH',
idempotencyKey: '11111111-1111-4111-8111-111111111111', idempotencyKey: '11111111-1111-4111-8111-111111111111',
}).success).toBe(false) }).success).toBe(false)
expect(startTrialSchema.parse({ plan: 'STARTER', billingPeriod: 'ANNUAL' })).toMatchObject({ currency: 'MAD' }) expect(startTrialSchema.parse({ plan: 'STARTER', billingPeriod: 'ANNUAL' })).toMatchObject({ currency: 'MAD' })
@@ -7,7 +7,6 @@ describe('payment schemas edge cases', () => {
expect(manualPaymentSchema.safeParse({ amount: 0, paymentMethod: 'CHECK' }).success).toBe(false) expect(manualPaymentSchema.safeParse({ amount: 0, paymentMethod: 'CHECK' }).success).toBe(false)
expect(manualPaymentSchema.safeParse({ amount: 100, paymentMethod: 'PAYPAL' }).success).toBe(false) expect(manualPaymentSchema.safeParse({ amount: 100, paymentMethod: 'PAYPAL' }).success).toBe(false)
expect(manualPaymentSchema.safeParse({ amount: 100, paymentMethod: 'CASH' }).success).toBe(false) expect(manualPaymentSchema.safeParse({ amount: 100, paymentMethod: 'CASH' }).success).toBe(false)
expect(manualPaymentSchema.safeParse({ amount: 100, paymentMethod: 'STRIPE' as any }).success).toBe(false)
}) })
it('validates refund and payment parameter payloads', () => { it('validates refund and payment parameter payloads', () => {
@@ -10,7 +10,7 @@ describe('manual subscription payment contracts', () => {
it('accepts only bank transfer and check manual checkout', () => { it('accepts only bank transfer and check manual checkout', () => {
const base = { plan: 'GROWTH', billingPeriod: 'ANNUAL', currency: 'MAD', idempotencyKey: crypto.randomUUID() } const base = { plan: 'GROWTH', billingPeriod: 'ANNUAL', currency: 'MAD', idempotencyKey: crypto.randomUUID() }
expect(manualCheckoutSchema.safeParse({ ...base, method: 'BANK_TRANSFER' }).success).toBe(true) expect(manualCheckoutSchema.safeParse({ ...base, method: 'BANK_TRANSFER' }).success).toBe(true)
expect(manualCheckoutSchema.safeParse({ ...base, method: 'STRIPE' }).success).toBe(false) expect(manualCheckoutSchema.safeParse({ ...base, method: 'CASH' }).success).toBe(false)
}) })
it('normalizes references without discarding the display value', () => { it('normalizes references without discarding the display value', () => {
@@ -18,7 +18,7 @@ describe('subscription.schemas edge contracts', () => {
expect(manualCheckoutSchema.parse(payload)).toEqual(payload) expect(manualCheckoutSchema.parse(payload)).toEqual(payload)
expect(manualCheckoutSchema.safeParse({ ...payload, currency: 'USD' }).success).toBe(false) expect(manualCheckoutSchema.safeParse({ ...payload, currency: 'USD' }).success).toBe(false)
expect(manualCheckoutSchema.safeParse({ ...payload, method: 'STRIPE' }).success).toBe(false) expect(manualCheckoutSchema.safeParse({ ...payload, method: 'CASH' }).success).toBe(false)
expect(manualCheckoutSchema.safeParse({ ...payload, idempotencyKey: 'not-a-uuid' }).success).toBe(false) expect(manualCheckoutSchema.safeParse({ ...payload, idempotencyKey: 'not-a-uuid' }).success).toBe(false)
}) })
-127
View File
@@ -1,127 +0,0 @@
import Stripe from 'stripe'
const STRIPE_API_KEY = process.env.STRIPE_API_KEY ?? ''
const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET ?? ''
let client: Stripe | null = null
function getClient() {
if (!client) {
client = new Stripe(STRIPE_API_KEY, {
apiVersion: '2026-06-24.dahlia',
appInfo: {
name: 'RentalDriveGo',
version: '1.0.0',
},
})
}
return client
}
function integrationIdentifier() {
const suffix = Math.random().toString(36).replace(/[^a-z]/g, '').slice(0, 8).padEnd(8, 'x')
return `rentaldrivego_${suffix}`
}
export interface StripeCheckoutParams {
amount: number
currency: string
orderId: string
description: string
customerEmail?: string | null
successUrl: string
cancelUrl: string
reservationId?: string
companyId: string
subscriptionId?: string
type: 'CHARGE' | 'DEPOSIT' | 'SUBSCRIPTION'
}
export interface StripeCheckoutResult {
checkoutUrl: string
sessionId: string
}
export async function createCheckoutSession(params: StripeCheckoutParams): Promise<StripeCheckoutResult> {
const session = await getClient().checkout.sessions.create({
mode: 'payment',
success_url: params.successUrl,
cancel_url: params.cancelUrl,
customer_email: params.customerEmail ?? undefined,
client_reference_id: params.orderId,
line_items: [
{
quantity: 1,
price_data: {
currency: params.currency.toLowerCase(),
unit_amount: params.amount,
product_data: {
name: params.description,
},
},
},
],
metadata: {
...(params.reservationId ? { reservationId: params.reservationId } : {}),
companyId: params.companyId,
...(params.subscriptionId ? { subscriptionId: params.subscriptionId } : {}),
type: params.type,
orderId: params.orderId,
},
payment_intent_data: {
metadata: {
...(params.reservationId ? { reservationId: params.reservationId } : {}),
companyId: params.companyId,
...(params.subscriptionId ? { subscriptionId: params.subscriptionId } : {}),
type: params.type,
orderId: params.orderId,
},
},
integration_identifier: integrationIdentifier(),
})
if (!session.url) {
throw new Error('Stripe checkout session did not include a checkout URL')
}
return { checkoutUrl: session.url, sessionId: session.id }
}
export function constructWebhookEvent(rawBody: string | Buffer, signature: string) {
return getClient().webhooks.constructEvent(rawBody, signature, STRIPE_WEBHOOK_SECRET)
}
export async function refundPaymentIntent(paymentIntentId: string, amount: number, reason?: string) {
return getClient().refunds.create({
payment_intent: paymentIntentId,
amount,
metadata: reason ? { reason } : undefined,
})
}
export function isConfigured(): boolean {
return getConfigurationStatus().configured
}
export function getConfigurationStatus() {
const problems: string[] = []
if (!STRIPE_API_KEY) {
problems.push('STRIPE_API_KEY is missing')
} else if (STRIPE_API_KEY.includes('placeholder')) {
problems.push('STRIPE_API_KEY is still a placeholder')
} else if (!STRIPE_API_KEY.startsWith('sk_') && !STRIPE_API_KEY.startsWith('rk_')) {
problems.push('STRIPE_API_KEY must be a Stripe secret or restricted key')
}
if (!STRIPE_WEBHOOK_SECRET) {
problems.push('STRIPE_WEBHOOK_SECRET is missing')
} else if (!STRIPE_WEBHOOK_SECRET.startsWith('whsec_')) {
problems.push('STRIPE_WEBHOOK_SECRET must be a Stripe webhook signing secret')
}
return {
configured: problems.length === 0,
problems,
}
}
@@ -72,7 +72,7 @@ describe('subscription and team API validation contracts', () => {
plan: 'PRO', plan: 'PRO',
billingPeriod: 'ANNUAL', billingPeriod: 'ANNUAL',
currency: 'MAD', currency: 'MAD',
method: 'STRIPE', method: 'CASH',
idempotencyKey: '11111111-1111-4111-8111-111111111111', idempotencyKey: '11111111-1111-4111-8111-111111111111',
}) })
@@ -12,7 +12,7 @@ const app = createApp()
describe('subscription and team public boundary smoke', () => { describe('subscription and team public boundary smoke', () => {
it('rejects malformed protected subscription checkout without leaking internals', async () => { it('rejects malformed protected subscription checkout without leaking internals', async () => {
const res = await request(app).post('/api/v1/subscriptions/manual-checkout').send({ method: 'STRIPE' }) const res = await request(app).post('/api/v1/subscriptions/manual-checkout').send({ method: 'CASH' })
expect([400, 401]).toContain(res.status) expect([400, 401]).toContain(res.status)
expect(JSON.stringify(res.body)).not.toContain('stack') expect(JSON.stringify(res.body)).not.toContain('stack')
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { parseBody, parseQuery } from '../../http/validate' import { parseBody, parseQuery } from '../../http/validate'
import { carplaceReservationSchema, paginationSchema } from '../../modules/carplace/carplace.schemas' import { carplaceReservationSchema, paginationSchema } from '../../modules/carplace/carplace.schemas'
import { paySchema } from '../../modules/site/site.schemas' import { manualCheckoutSchema } from '../../modules/subscriptions/subscription.schemas'
function reqWith(body: unknown, query: unknown = {}) { function reqWith(body: unknown, query: unknown = {}) {
return { body, query, params: {} } as any return { body, query, params: {} } as any
@@ -15,13 +15,14 @@ describe('public validation boundaries', () => {
}) })
}) })
it('blocks unsupported public payment providers before service orchestration', () => { it('blocks unsupported payment methods before service orchestration', () => {
expect(() => parseBody(paySchema, reqWith({ expect(() => parseBody(manualCheckoutSchema, reqWith({
provider: 'STRIPE', plan: 'PRO',
successUrl: 'https://ok.example.test', billingPeriod: 'MONTHLY',
failureUrl: 'https://fail.example.test', currency: 'MAD',
accessToken: 'booking-access-token-123', method: 'CASH',
}))).toThrow('Invalid enum value') idempotencyKey: '11111111-1111-4111-8111-111111111111',
}))).toThrow()
}) })
it('requires enough anonymous carplace reservation identity to create a booking request', () => { it('requires enough anonymous carplace reservation identity to create a booking request', () => {
@@ -18,7 +18,7 @@ describe('schema boundary integration markers', () => {
plan: 'PRO', plan: 'PRO',
billingPeriod: 'MONTHLY', billingPeriod: 'MONTHLY',
currency: 'MAD', currency: 'MAD',
method: 'STRIPE', method: 'CASH',
idempotencyKey: '11111111-1111-4111-8111-111111111111', idempotencyKey: '11111111-1111-4111-8111-111111111111',
}).success).toBe(false) }).success).toBe(false)
}) })