Files
vyndr/tests/unit/stripeService.test.js
T
builtbykev eb443232fb feat: Feature 3.4 — Stripe integration with founder code system
Subscription billing:
- POST /api/stripe/checkout — creates Stripe Checkout session
- POST /api/stripe/webhook — handles lifecycle events (raw body)
- POST /api/stripe/portal — customer self-service management
- GET /api/stripe/status — current subscription info

Founder code system:
- Validates codes against env var list with expiry date
- Routes to founder Stripe Price IDs (locked rate for life)
- 4 price objects: analyst, analyst-founder, desk, desk-founder

Webhook events handled:
- checkout.session.completed → tier update + founder status
- customer.subscription.deleted → revert to free tier
- invoice.payment_failed → logged

Lazy Stripe init (no API key required at import time).
Raw body middleware for webhook signature verification.

16 new tests, 237 total (210 Node.js + 27 Python), all passing.
Phase 3 Web MVP COMPLETE. All roadmap features shipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:30:42 -04:00

58 lines
1.8 KiB
JavaScript

process.env.STRIPE_SECRET_KEY = 'sk_test_dummy';
jest.mock('../../src/utils/supabase', () => ({
getSupabaseServiceClient: () => ({ from: jest.fn() }),
}));
const { isFounderCodeValid, getPriceId } = require('../../src/services/stripeService');
describe('stripeService', () => {
describe('isFounderCodeValid', () => {
test('valid founder code returns true', () => {
expect(isFounderCodeValid('FOUNDER2026')).toBe(true);
expect(isFounderCodeValid('BETONBLK')).toBe(true);
});
test('case insensitive', () => {
expect(isFounderCodeValid('founder2026')).toBe(true);
});
test('invalid code returns false', () => {
expect(isFounderCodeValid('INVALID')).toBe(false);
});
test('null/empty returns false', () => {
expect(isFounderCodeValid(null)).toBe(false);
expect(isFounderCodeValid('')).toBe(false);
});
});
describe('getPriceId', () => {
test('analyst without founder code returns standard price', () => {
const id = getPriceId('analyst', null);
expect(id).toContain('analyst');
expect(id).not.toContain('founder');
});
test('analyst with valid founder code returns founder price', () => {
const id = getPriceId('analyst', 'FOUNDER2026');
expect(id).toContain('founder');
});
test('desk without founder code returns standard price', () => {
const id = getPriceId('desk', null);
expect(id).toContain('desk');
expect(id).not.toContain('founder');
});
test('desk with valid founder code returns founder price', () => {
const id = getPriceId('desk', 'BETONBLK');
expect(id).toContain('founder');
});
test('invalid tier throws', () => {
expect(() => getPriceId('gold', null)).toThrow('Invalid tier');
});
});
});