zappier-edge/tests/health-proxy-credits.test.ts

87 lines
3.4 KiB
TypeScript

import request from 'supertest';
import { buildApp } from '../src/app';
const KEY = 'key-ada';
const ADMIN = { 'x-admin-key': 'admin-dev-key' };
describe('zappier-edge operational wiring', () => {
it('GET /health is public', async () => {
const { app } = buildApp();
const res = await request(app).get('/health');
expect(res.status).toBe(200);
expect(res.body.role).toBe('zappier-edge');
});
it('proxies timestamp to middleware when ZAPPIER_UPSTREAM is set', async () => {
process.env.ZAPPIER_UPSTREAM = 'http://upstream.test';
const orig = globalThis.fetch;
globalThis.fetch = jest.fn(async (url: string | URL) => {
expect(String(url)).toContain('/zapier/v1/timestamp');
return new Response(JSON.stringify({ jobId: 'mw-1', sha256: 'abc' }), {
status: 202,
headers: { 'content-type': 'application/json' },
});
}) as typeof fetch;
try {
const { app } = buildApp();
const res = await request(app).post('/v1/timestamp').set('x-api-key', KEY).send({ data: 'hello' });
expect(res.status).toBe(202);
expect(res.body.jobId).toBe('mw-1');
expect(res.body.quote.totalCents).toBeGreaterThanOrEqual(0);
} finally {
globalThis.fetch = orig;
delete process.env.ZAPPIER_UPSTREAM;
}
});
it('customers CS and sales can review a statement', async () => {
const { app } = buildApp();
await request(app)
.post('/admin/api/credits')
.set(ADMIN)
.send({ customerId: 'cust_1', cents: 250, reason: 'goodwill', agent: 'cs' });
const st = await request(app).get('/admin/api/statement/cust_1').set(ADMIN);
expect(st.status).toBe(200);
expect(st.body.prepaidCents).toBeGreaterThanOrEqual(250);
expect(st.body.credits.length).toBeGreaterThan(0);
});
it('customer service can add prepaid credits', async () => {
const { app } = buildApp();
const add = await request(app)
.post('/admin/api/credits')
.set(ADMIN)
.send({ customerId: 'cust_1', cents: 500, reason: 'goodwill', agent: 'cs-anna' });
expect(add.status).toBe(201);
expect(add.body.cents).toBe(500);
const list = await request(app).get('/admin/api/credits?customerId=cust_1').set(ADMIN);
expect(list.body.credits[0].reason).toBe('goodwill');
});
it('sales quote returns per-customer multiplier', async () => {
const { app } = buildApp();
const res = await request(app).get('/admin/api/sales/quote/cust_2').set(ADMIN);
expect(res.status).toBe(200);
expect(res.body.tierId).toBe('pro');
});
it('exports issued invoices as QuickBooks IIF', async () => {
const { app, usage } = buildApp();
usage.record({
customerId: 'cust_2',
endpointId: 'transform',
cents: 400,
metadataBytes: 0,
attachmentBytes: 0,
timestamp: new Date('2026-07-05T10:00:00Z'),
});
await request(app).post('/admin/api/invoices/generate').set(ADMIN).send({ period: '2026-07' });
await request(app).post('/admin/api/invoices/INV-2026-07-0001/issue').set(ADMIN);
const iif = await request(app).get('/admin/api/exports/quickbooks.iif?period=2026-07').set(ADMIN);
expect(iif.status).toBe(200);
expect(iif.text).toContain('TRNS');
expect(iif.text).toContain('INV-2026-07-0001');
const csv = await request(app).get('/admin/api/exports/accounting.csv?period=2026-07').set(ADMIN);
expect(csv.text).toContain('invoice_id');
});
});