Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Commands

- **Test all**: `bun test` or `vitest`
- **Test all**: `bun test`
- **Test single file**: `vitest src/__tests__/unit/path/to/test.test.ts`
- **Test with UI**: `bun run test:ui`
- **Dev server**: `bun run dev:backend` (auto-reload on port 8069)
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"test": "vitest",
"test:ui": "vitest --ui",
"start": "bun run src/server.ts",
"init_key": "bun run src/utils/generateInitialAPIKey.ts"
"init_key": "bun run src/utils/generateInitialAPIKey.ts",
"format": "bunx prettier --write ."
},
"devDependencies": {
"@types/bun": "latest",
Expand Down
24 changes: 24 additions & 0 deletions src/__tests__/unit/http/createdCheckout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,24 @@ class PaymentMock {
public userId: string;
public data: unknown;
public readonly type = "PAYMENT" as const;
public reported_timestamp = { toISO: () => "2024-01-01T00:00:00.000Z" };

constructor(userId: string, data: unknown) {
this.userId = userId;
this.data = data;
paymentConstructorCalls.push({ userId, data });
}

serialize() {
return {
SQL: {
type: this.type,
userId: this.userId,
reported_timestamp: this.reported_timestamp,
data: this.data,
},
};
}
}

// Mock modules
Expand All @@ -50,12 +62,24 @@ vi.mock("../../../events/RawEvents/Payment.ts", () => ({
public userId: string;
public data: unknown;
public readonly type = "PAYMENT" as const;
public reported_timestamp = { toISO: () => "2024-01-01T00:00:00.000Z" };

constructor(userId: string, data: unknown) {
this.userId = userId;
this.data = data;
paymentConstructorCalls.push({ userId, data });
}

serialize() {
return {
SQL: {
type: this.type,
userId: this.userId,
reported_timestamp: this.reported_timestamp,
data: this.data,
},
};
}
},
}));

Expand Down
38 changes: 28 additions & 10 deletions src/__tests__/unit/storage/postgres/addKey.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ describe("PostgresAdapter - addKey handler", () => {
]);

const adapter = new PostgresAdapter(addKeyEvent);
const result = await adapter.add();
const serialized = addKeyEvent.serialize();
const result = await adapter.add(serialized);

expect(result).toEqual({ id: "api-key-id-123" });
});
Expand All @@ -63,7 +64,8 @@ describe("PostgresAdapter - addKey handler", () => {
]);

const adapter = new PostgresAdapter(addKeyEvent);
await adapter.add();
const serialized = addKeyEvent.serialize();
await adapter.add(serialized);

const insertCall = mockTransaction.values.mock.calls[0][0];
expect(insertCall.name).toBe(keyData.name);
Expand All @@ -88,7 +90,10 @@ describe("PostgresAdapter - addKey handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow("Missing data field");
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Missing data field",
);
});

it("throws error when name is missing", async () => {
Expand All @@ -112,7 +117,10 @@ describe("PostgresAdapter - addKey handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow("Invalid or missing 'name'");
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Invalid or missing 'name'",
);
});

it("throws error when key is missing", async () => {
Expand All @@ -136,7 +144,10 @@ describe("PostgresAdapter - addKey handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow("Invalid or missing 'key'");
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Invalid or missing 'key'",
);
});

it("throws error when key is empty string", async () => {
Expand All @@ -162,7 +173,10 @@ describe("PostgresAdapter - addKey handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow("API key cannot be empty");
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"API key cannot be empty",
);
});

it("throws error when timestamp is empty", async () => {
Expand All @@ -186,7 +200,8 @@ describe("PostgresAdapter - addKey handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow(
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Timestamp is undefined or empty",
);
});
Expand All @@ -205,7 +220,8 @@ describe("PostgresAdapter - addKey handler", () => {
);

const adapter = new PostgresAdapter(addKeyEvent);
await expect(adapter.add()).rejects.toThrow();
const serialized = addKeyEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow();
});

it("handles empty API key ID response", async () => {
Expand All @@ -218,7 +234,8 @@ describe("PostgresAdapter - addKey handler", () => {
mockTransaction.returning.mockResolvedValueOnce([]);

const adapter = new PostgresAdapter(addKeyEvent);
await expect(adapter.add()).rejects.toThrow(
const serialized = addKeyEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow(
"API key insert returned no record",
);
});
Expand All @@ -233,7 +250,8 @@ describe("PostgresAdapter - addKey handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{}]);

const adapter = new PostgresAdapter(addKeyEvent);
await expect(adapter.add()).rejects.toThrow(
const serialized = addKeyEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow(
"API key insert returned object without id field",
);
});
Expand Down
27 changes: 18 additions & 9 deletions src/__tests__/unit/storage/postgres/addPayment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-123" }]);

const adapter = new PostgresAdapter(paymentEvent, "api-key-123");
await adapter.add();
const serialized = paymentEvent.serialize();
await adapter.add(serialized);

const eventInsertCall = mockTransaction.values.mock.calls[1][0];
expect(eventInsertCall.api_keyId).toBe("api-key-123");
Expand All @@ -56,7 +57,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-456" }]);

const adapter = new PostgresAdapter(paymentEvent);
await adapter.add();
const serialized = paymentEvent.serialize();
await adapter.add(serialized);

const eventInsertCall = mockTransaction.values.mock.calls[1][0];
expect(eventInsertCall.api_keyId).toBeUndefined();
Expand All @@ -70,7 +72,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-3" }]);

const adapter = new PostgresAdapter(paymentEvent);
await adapter.add();
const serialized = paymentEvent.serialize();
await adapter.add(serialized);

const paymentInsertCall = mockTransaction.values.mock.calls[2][0];
expect(paymentInsertCall.creditAmount).toBe(15000);
Expand All @@ -85,7 +88,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-pos" }]);

const adapter = new PostgresAdapter(paymentEvent);
await adapter.add();
const serialized = paymentEvent.serialize();
await adapter.add(serialized);

const paymentInsertCall = mockTransaction.values.mock.calls[2][0];
expect(paymentInsertCall.creditAmount).toBe(1);
Expand All @@ -111,7 +115,8 @@ describe("PostgresAdapter - addPayment handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow(/positive/);
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(/positive/);
});

it("throws error when creditAmount is negative", async () => {
Expand All @@ -131,7 +136,8 @@ describe("PostgresAdapter - addPayment handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow(/positive/);
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(/positive/);
});

it("throws error when timestamp is empty", async () => {
Expand All @@ -155,7 +161,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([]);

const adapter = new PostgresAdapter(invalidEvent as any);
await expect(adapter.add()).rejects.toThrow(
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Timestamp is undefined or empty",
);
});
Expand All @@ -173,7 +180,8 @@ describe("PostgresAdapter - addPayment handler", () => {
);

const adapter = new PostgresAdapter(paymentEvent);
await expect(adapter.add()).rejects.toThrow();
const serialized = paymentEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow();
});

it("handles empty event ID response", async () => {
Expand All @@ -185,7 +193,8 @@ describe("PostgresAdapter - addPayment handler", () => {
mockTransaction.returning.mockResolvedValueOnce([]);

const adapter = new PostgresAdapter(paymentEvent);
await expect(adapter.add()).rejects.toThrow(
const serialized = paymentEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow(
"Event insert returned no ID",
);
});
Expand Down
21 changes: 14 additions & 7 deletions src/__tests__/unit/storage/postgres/addSdkCall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
]);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key-123");
await adapter.add();
const serialized = sdkCallEvent.serialize();
await adapter.add(serialized);

const eventInsertCall = mockTransaction.values.mock.calls[1][0];
expect(eventInsertCall.api_keyId).toBe("api-key-123");
Expand All @@ -60,7 +61,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-456" }]);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key-456");
await adapter.add();
const serialized = sdkCallEvent.serialize();
await adapter.add(serialized);

const sdkCallInsertCall = mockTransaction.values.mock.calls[2][0];
expect(sdkCallInsertCall.debitAmount).toBe(2500);
Expand All @@ -75,7 +77,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-1" }]);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key-1");
await adapter.add();
const serialized = sdkCallEvent.serialize();
await adapter.add(serialized);

const eventInsertCall = mockTransaction.values.mock.calls[1][0];
expect(eventInsertCall).toHaveProperty("reported_timestamp");
Expand All @@ -91,7 +94,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
mockTransaction.returning.mockResolvedValueOnce([{ id: "event-id-pos" }]);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key-pos");
await adapter.add();
const serialized = sdkCallEvent.serialize();
await adapter.add(serialized);

const insertedValues = mockTransaction.values.mock.calls.map(
(c: any) => c[0],
Expand All @@ -117,7 +121,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key");
await expect(adapter.add()).rejects.toThrow();
const serialized = sdkCallEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow();
});

it("handles empty event ID response", async () => {
Expand All @@ -129,7 +134,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
mockTransaction.returning.mockResolvedValueOnce([]);

const adapter = new PostgresAdapter(sdkCallEvent, "api-key");
await expect(adapter.add()).rejects.toThrow(
const serialized = sdkCallEvent.serialize();
await expect(adapter.add(serialized)).rejects.toThrow(
"Event insert returned no ID",
);
});
Expand All @@ -155,7 +161,8 @@ describe("PostgresAdapter - addSdkCall handler", () => {
};

const adapter = new PostgresAdapter(invalidEvent as any, "api-key");
await expect(adapter.add()).rejects.toThrow(
const serialized = invalidEvent.serialize() as any;
await expect(adapter.add(serialized)).rejects.toThrow(
"Timestamp is undefined or empty",
);
});
Expand Down
Loading