Initial import of zappier-edge from zapier monorepo
This commit is contained in:
commit
6ae11f8875
120 changed files with 19867 additions and 0 deletions
116
tests/db-customer.test.ts
Normal file
116
tests/db-customer.test.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import Database from 'better-sqlite3';
|
||||
import { Customer } from '../src/auth';
|
||||
import { SqliteCustomerRepo } from '../src/db/customer-repo';
|
||||
|
||||
const customer = (apiKey: string): Customer => ({
|
||||
id: 'cust_1',
|
||||
name: 'Ada',
|
||||
tierId: 'pro',
|
||||
apiKey,
|
||||
stripeCustomerId: 'cus_123',
|
||||
});
|
||||
|
||||
describe('SqliteCustomerRepo', () => {
|
||||
it('finds a customer by API key', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
expect(repo.findByApiKey('key-ada')?.tierId).toBe('pro');
|
||||
});
|
||||
|
||||
it('returns undefined for an unknown key', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
expect(repo.findByApiKey('wrong')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('lists all customers with their Stripe ids', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
const all = repo.list();
|
||||
expect(all).toHaveLength(1);
|
||||
expect(all[0].stripeCustomerId).toBe('cus_123');
|
||||
});
|
||||
|
||||
it('seeds only when the table is empty', () => {
|
||||
const db = new Database(':memory:');
|
||||
new SqliteCustomerRepo(db, [customer('key-ada')]);
|
||||
const again = new SqliteCustomerRepo(db, [customer('key-other')]);
|
||||
expect(again.list().map((c) => c.apiKey)).toEqual(['key-ada']);
|
||||
});
|
||||
|
||||
it('save() upserts including the multiplier override', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
repo.save({ ...customer('key-ada'), tierId: 'business', multiplierOverride: 0.4 });
|
||||
const updated = repo.findByApiKey('key-ada');
|
||||
expect(updated?.tierId).toBe('business');
|
||||
expect(updated?.multiplierOverride).toBe(0.4);
|
||||
expect(repo.list()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('round-trips billingType and email', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
repo.save({ ...customer('key-ada'), billingType: 'purchase_order', email: 'ada@example.com' });
|
||||
const updated = repo.findByApiKey('key-ada');
|
||||
expect(updated?.billingType).toBe('purchase_order');
|
||||
expect(updated?.email).toBe('ada@example.com');
|
||||
});
|
||||
|
||||
it('migrates a legacy table, defaulting billingType to stripe', () => {
|
||||
const db = new Database(':memory:');
|
||||
db.exec(`CREATE TABLE customers (
|
||||
id TEXT PRIMARY KEY, name TEXT NOT NULL, tier_id TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL UNIQUE, stripe_customer_id TEXT, multiplier_override REAL
|
||||
)`);
|
||||
db.prepare(
|
||||
`INSERT INTO customers (id, name, tier_id, api_key) VALUES ('cust_1', 'Ada', 'pro', 'key-ada')`,
|
||||
).run();
|
||||
const repo = new SqliteCustomerRepo(db);
|
||||
const migrated = repo.findByApiKey('key-ada');
|
||||
expect(migrated?.billingType).toBe('stripe');
|
||||
expect(migrated?.email).toBeUndefined();
|
||||
// and new columns are writable after migration
|
||||
repo.save({ ...migrated!, billingType: 'purchase_order' });
|
||||
expect(repo.findByApiKey('key-ada')?.billingType).toBe('purchase_order');
|
||||
});
|
||||
|
||||
it('finds a customer by email (case-insensitive)', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [
|
||||
{ ...customer('key-ada'), email: 'Ada@Example.com' },
|
||||
]);
|
||||
expect(repo.findByEmail('ada@example.com')?.id).toBe('cust_1');
|
||||
expect(repo.findByEmail('nobody@example.com')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('round-trips portal identity fields', () => {
|
||||
const repo = new SqliteCustomerRepo(new Database(':memory:'), [customer('key-ada')]);
|
||||
repo.save({
|
||||
...customer('key-ada'),
|
||||
passwordHash: 'scrypt:16384:8:1:c2FsdA==:aGFzaA==',
|
||||
totpSecret: 'ABC234',
|
||||
totpEnabled: true,
|
||||
balanceCents: 2500,
|
||||
emailInvoicing: true,
|
||||
});
|
||||
const updated = repo.findByApiKey('key-ada');
|
||||
expect(updated?.passwordHash).toBe('scrypt:16384:8:1:c2FsdA==:aGFzaA==');
|
||||
expect(updated?.totpSecret).toBe('ABC234');
|
||||
expect(updated?.totpEnabled).toBe(true);
|
||||
expect(updated?.balanceCents).toBe(2500);
|
||||
expect(updated?.emailInvoicing).toBe(true);
|
||||
});
|
||||
|
||||
it('defaults portal identity fields for legacy rows', () => {
|
||||
const db = new Database(':memory:');
|
||||
db.exec(`CREATE TABLE customers (
|
||||
id TEXT PRIMARY KEY, name TEXT NOT NULL, tier_id TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL UNIQUE, stripe_customer_id TEXT, multiplier_override REAL
|
||||
)`);
|
||||
db.prepare(
|
||||
`INSERT INTO customers (id, name, tier_id, api_key) VALUES ('cust_1', 'Ada', 'pro', 'key-ada')`,
|
||||
).run();
|
||||
const repo = new SqliteCustomerRepo(db);
|
||||
const migrated = repo.findByApiKey('key-ada');
|
||||
expect(migrated?.passwordHash).toBeUndefined();
|
||||
expect(migrated?.totpSecret).toBeUndefined();
|
||||
expect(migrated?.totpEnabled).toBe(false);
|
||||
expect(migrated?.balanceCents).toBe(0);
|
||||
expect(migrated?.emailInvoicing).toBe(false);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue