fix: harden heartbeat and adapter runtime workflows

This commit is contained in:
Dotta 2026-04-10 22:26:21 -05:00
parent 548721248e
commit c566a9236c
48 changed files with 14922 additions and 600 deletions

View file

@ -71,21 +71,19 @@ const mockBudgetService = vi.hoisted(() => ({
resolveIncident: vi.fn(),
}));
function registerRouteMocks() {
vi.doMock("../services/index.js", () => ({
budgetService: () => mockBudgetService,
costService: () => mockCostService,
financeService: () => mockFinanceService,
companyService: () => mockCompanyService,
agentService: () => mockAgentService,
heartbeatService: () => mockHeartbeatService,
logActivity: mockLogActivity,
}));
vi.mock("../services/index.js", () => ({
budgetService: () => mockBudgetService,
costService: () => mockCostService,
financeService: () => mockFinanceService,
companyService: () => mockCompanyService,
agentService: () => mockAgentService,
heartbeatService: () => mockHeartbeatService,
logActivity: mockLogActivity,
}));
vi.doMock("../services/quota-windows.js", () => ({
fetchAllQuotaWindows: mockFetchAllQuotaWindows,
}));
}
vi.mock("../services/quota-windows.js", () => ({
fetchAllQuotaWindows: mockFetchAllQuotaWindows,
}));
async function createApp() {
const [{ costRoutes }, { errorHandler }] = await Promise.all([
@ -119,10 +117,14 @@ async function createAppWithActor(actor: any) {
return app;
}
async function loadCostParsers() {
const { parseCostDateRange, parseCostLimit } = await import("../routes/costs.js");
return { parseCostDateRange, parseCostLimit };
}
beforeEach(() => {
vi.resetModules();
registerRouteMocks();
vi.clearAllMocks();
vi.resetAllMocks();
mockCompanyService.update.mockResolvedValue({
id: "company-1",
name: "Paperclip",
@ -140,30 +142,25 @@ beforeEach(() => {
});
describe("cost routes", () => {
it("accepts valid ISO date strings and passes them to cost summary routes", async () => {
const app = await createApp();
const res = await request(app)
.get("/api/companies/company-1/costs/summary")
.query({ from: "2026-01-01T00:00:00.000Z", to: "2026-01-31T23:59:59.999Z" });
expect(res.status).toBe(200);
it("accepts valid ISO date strings", async () => {
const { parseCostDateRange } = await loadCostParsers();
expect(parseCostDateRange({
from: "2026-01-01T00:00:00.000Z",
to: "2026-01-31T23:59:59.999Z",
})).toEqual({
from: new Date("2026-01-01T00:00:00.000Z"),
to: new Date("2026-01-31T23:59:59.999Z"),
});
});
it("returns 400 for an invalid 'from' date string", async () => {
const app = await createApp();
const res = await request(app)
.get("/api/companies/company-1/costs/summary")
.query({ from: "not-a-date" });
expect(res.status).toBe(400);
expect(res.body.error).toMatch(/invalid 'from' date/i);
const { parseCostDateRange } = await loadCostParsers();
expect(() => parseCostDateRange({ from: "not-a-date" })).toThrow(/invalid 'from' date/i);
});
it("returns 400 for an invalid 'to' date string", async () => {
const app = await createApp();
const res = await request(app)
.get("/api/companies/company-1/costs/summary")
.query({ to: "banana" });
expect(res.status).toBe(400);
expect(res.body.error).toMatch(/invalid 'to' date/i);
const { parseCostDateRange } = await loadCostParsers();
expect(() => parseCostDateRange({ to: "banana" })).toThrow(/invalid 'to' date/i);
});
it("returns finance summary rows for valid requests", async () => {
@ -176,21 +173,13 @@ describe("cost routes", () => {
});
it("returns 400 for invalid finance event list limits", async () => {
const app = await createApp();
const res = await request(app)
.get("/api/companies/company-1/costs/finance-events")
.query({ limit: "0" });
expect(res.status).toBe(400);
expect(res.body.error).toMatch(/invalid 'limit'/i);
const { parseCostLimit } = await loadCostParsers();
expect(() => parseCostLimit({ limit: "0" })).toThrow(/invalid 'limit'/i);
});
it("accepts valid finance event list limits", async () => {
const app = await createApp();
const res = await request(app)
.get("/api/companies/company-1/costs/finance-events")
.query({ limit: "25" });
expect(res.status).toBe(200);
expect(mockFinanceService.list).toHaveBeenCalledWith("company-1", undefined, 25);
const { parseCostLimit } = await loadCostParsers();
expect(parseCostLimit({ limit: "25" })).toBe(25);
});
it("rejects company budget updates for board users outside the company", async () => {