Initial import of zappier-edge from zapier monorepo
This commit is contained in:
commit
f0d193b221
120 changed files with 19867 additions and 0 deletions
86
tests/invoicing.test.ts
Normal file
86
tests/invoicing.test.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { buildInvoice, Invoice } from '../src/invoicing';
|
||||
import { Customer } from '../src/auth';
|
||||
import { TierConfig } from '../src/pricing';
|
||||
import { UsageEntry } from '../src/usage';
|
||||
|
||||
const pro: TierConfig = { id: 'pro', name: 'Pro', multiplier: 0.5, monthlyCreditCents: 1000 };
|
||||
|
||||
const customer: Customer = {
|
||||
id: 'cust_2',
|
||||
name: 'Grace',
|
||||
tierId: 'pro',
|
||||
apiKey: 'key-grace',
|
||||
stripeCustomerId: 'cus_123',
|
||||
};
|
||||
|
||||
const entry = (endpointId: string, cents: number): UsageEntry => ({
|
||||
customerId: customer.id,
|
||||
endpointId,
|
||||
cents,
|
||||
metadataBytes: 0,
|
||||
attachmentBytes: 0,
|
||||
timestamp: new Date('2026-07-10T12:00:00Z'),
|
||||
});
|
||||
|
||||
describe('buildInvoice', () => {
|
||||
it('groups usage entries into lines per endpoint, sorted', () => {
|
||||
const inv = buildInvoice({
|
||||
customer,
|
||||
period: '2026-07',
|
||||
sequence: 1,
|
||||
tier: pro,
|
||||
entries: [entry('transform', 3), entry('storage', 6), entry('transform', 3)],
|
||||
});
|
||||
expect(inv.lines).toEqual([
|
||||
{ endpointId: 'storage', calls: 1, cents: 6 },
|
||||
{ endpointId: 'transform', calls: 2, cents: 6 },
|
||||
]);
|
||||
expect(inv.totalCents).toBe(12);
|
||||
});
|
||||
|
||||
it('applies a partial monthly credit', () => {
|
||||
const inv = buildInvoice({
|
||||
customer,
|
||||
period: '2026-07',
|
||||
sequence: 1,
|
||||
tier: pro,
|
||||
entries: [entry('storage', 1500)],
|
||||
});
|
||||
expect(inv.totalCents).toBe(1500);
|
||||
expect(inv.creditCents).toBe(1000);
|
||||
expect(inv.billableCents).toBe(500);
|
||||
});
|
||||
|
||||
it('floors billable at zero when credit exceeds usage', () => {
|
||||
const inv = buildInvoice({
|
||||
customer,
|
||||
period: '2026-07',
|
||||
sequence: 1,
|
||||
tier: pro,
|
||||
entries: [entry('storage', 400)],
|
||||
});
|
||||
expect(inv.creditCents).toBe(400);
|
||||
expect(inv.billableCents).toBe(0);
|
||||
});
|
||||
|
||||
it('formats the id as INV-<period>-<padded sequence> and starts as draft', () => {
|
||||
const inv = buildInvoice({ customer, period: '2026-07', sequence: 7, tier: pro, entries: [] });
|
||||
expect(inv.id).toBe('INV-2026-07-0007');
|
||||
expect(inv.status).toBe('draft');
|
||||
expect(inv.billingType).toBe('stripe');
|
||||
});
|
||||
|
||||
it('carries purchase-order billing fields', () => {
|
||||
const poCustomer: Customer = { ...customer, billingType: 'purchase_order' };
|
||||
const inv = buildInvoice({
|
||||
customer: poCustomer,
|
||||
period: '2026-07',
|
||||
sequence: 2,
|
||||
tier: pro,
|
||||
entries: [entry('storage', 2000)],
|
||||
poNumber: 'PO-9982',
|
||||
});
|
||||
expect(inv.billingType).toBe('purchase_order');
|
||||
expect(inv.poNumber).toBe('PO-9982');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue