Compose-ready workspace: packages/zappier (rate card, portal, Stripe), packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier (CLI app), vendor/zapier-platform, and research/zapier vendor corpus. Gate 0 structure checks pass. Product code and research are not yet wired.
76 lines
2.3 KiB
JavaScript
76 lines
2.3 KiB
JavaScript
/**
|
|
* GATE 5 — Auth + entitlement HTTP tests
|
|
*/
|
|
|
|
import { describe, it, before, after, beforeEach, afterEach } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createApp } from '../../src/app.js';
|
|
import { useTempStore, seedFreeTenant } from '../helpers.js';
|
|
import { incrementUsage } from '../../src/store/usage.js';
|
|
import { PLAN_LIMITS } from '../../src/config.js';
|
|
import { checkEntitlement } from '../../src/services/entitlementService.js';
|
|
import { AppError } from '../../src/errors.js';
|
|
|
|
describe('auth + entitlements HTTP', () => {
|
|
/** @type {ReturnType<typeof useTempStore>} */
|
|
let ctx;
|
|
/** @type {import('http').Server} */
|
|
let server;
|
|
/** @type {number} */
|
|
let port;
|
|
/** @type {string} */
|
|
let apiKey;
|
|
|
|
before(() => {
|
|
ctx = useTempStore();
|
|
const seeded = seedFreeTenant();
|
|
apiKey = seeded.apiKey;
|
|
|
|
const app = createApp({ load: false });
|
|
return new Promise((resolve) => {
|
|
server = app.listen(0, '127.0.0.1', () => {
|
|
port = server.address().port;
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
|
|
after(async () => {
|
|
await new Promise((resolve) => server.close(resolve));
|
|
ctx.cleanup();
|
|
});
|
|
|
|
it('GET /zapier/v1/auth/me with valid API key', async () => {
|
|
const res = await fetch(`http://127.0.0.1:${port}/zapier/v1/auth/me`, {
|
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
});
|
|
assert.equal(res.status, 200);
|
|
const body = await res.json();
|
|
assert.equal(body.valid, true);
|
|
assert.equal(body.plan, 'free');
|
|
assert.ok(body.tenantId);
|
|
assert.ok(body.usage);
|
|
});
|
|
|
|
it('invalid key returns 401', async () => {
|
|
const res = await fetch(`http://127.0.0.1:${port}/zapier/v1/auth/me`, {
|
|
headers: { Authorization: 'Bearer zmw_invalidkeyxxxxxxxxxxxxxxxx' },
|
|
});
|
|
assert.equal(res.status, 401);
|
|
const body = await res.json();
|
|
assert.equal(body.code, 'UNAUTHORIZED');
|
|
});
|
|
|
|
it('exceeding free timestamp quota throws 402 QUOTA_EXCEEDED', () => {
|
|
const tenantId = 'tenant-test-free';
|
|
const limit = PLAN_LIMITS.free.timestamps;
|
|
// force usage to limit
|
|
for (let i = 0; i < limit; i += 1) {
|
|
incrementUsage(tenantId, 'timestamps', 1);
|
|
}
|
|
assert.throws(
|
|
() => checkEntitlement(tenantId, 'timestamp'),
|
|
(err) => err instanceof AppError && err.status === 402 && err.code === 'QUOTA_EXCEEDED',
|
|
);
|
|
});
|
|
});
|