refactor: fix webhook create/update serialization, add payload types, and MEMORY_CATEGORIZED event (#4429)
Co-authored-by: Saket Aryan <saketaryan2002@gmail.com>
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* Integration tests: User management and project configuration.
|
||||
* Integration tests: User management, project configuration, and webhooks.
|
||||
*
|
||||
* Tests users(), getProject(), and updateProject() against the real API.
|
||||
*
|
||||
* Note: Webhook tests (createWebhook, updateWebhook) are excluded because
|
||||
* the SDK has a known bug where it sends camelCase keys (eventTypes) instead
|
||||
* of snake_case (event_types). These will be added once the SDK is fixed.
|
||||
* Tests users(), getProject(), updateProject(), and webhook CRUD against the real API.
|
||||
*
|
||||
* Run: MEM0_API_KEY=your-key npx jest management.test.ts --forceExit
|
||||
*/
|
||||
import { MemoryClient } from "../../mem0";
|
||||
import { WebhookEvent } from "../../mem0.types";
|
||||
import { randomUUID } from "crypto";
|
||||
import {
|
||||
describeIntegration,
|
||||
@@ -17,6 +14,7 @@ import {
|
||||
suppressTelemetryNoise,
|
||||
seedTestMemories,
|
||||
cleanupTestUser,
|
||||
withRetry,
|
||||
} from "./helpers";
|
||||
|
||||
jest.setTimeout(120_000);
|
||||
@@ -95,4 +93,115 @@ describeIntegration("MemoryClient Integration — Users & Project", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Webhooks ──────────────────────────────────────────────
|
||||
describe("webhook management", () => {
|
||||
let createdWebhookId: string;
|
||||
const hookName = `test-hook-${randomUUID().slice(0, 8)}`;
|
||||
const hookUrl = `https://example.com/webhook/${randomUUID().slice(0, 8)}`;
|
||||
const updatedName = `updated-hook-${randomUUID().slice(0, 8)}`;
|
||||
|
||||
afterAll(async () => {
|
||||
if (createdWebhookId) {
|
||||
try {
|
||||
await client.deleteWebhook({ webhookId: createdWebhookId });
|
||||
} catch {
|
||||
// ignore — may already be deleted
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Create ────────────────────────────────────────────
|
||||
test("createWebhook returns a webhook_id", async () => {
|
||||
const result = await withRetry(() =>
|
||||
client.createWebhook({
|
||||
name: hookName,
|
||||
url: hookUrl,
|
||||
eventTypes: [WebhookEvent.MEMORY_ADDED, WebhookEvent.MEMORY_UPDATED],
|
||||
}),
|
||||
);
|
||||
createdWebhookId = result.webhook_id!;
|
||||
expect(result.webhook_id).toBeDefined();
|
||||
});
|
||||
|
||||
test("createWebhook returns the correct name", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const wh = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(wh!.name).toBe(hookName);
|
||||
});
|
||||
|
||||
test("createWebhook returns the correct url", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const wh = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(wh!.url).toBe(hookUrl);
|
||||
});
|
||||
|
||||
test("createWebhook returns the correct event_types", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const wh = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(wh!.event_types?.sort()).toStrictEqual(
|
||||
[WebhookEvent.MEMORY_ADDED, WebhookEvent.MEMORY_UPDATED].sort(),
|
||||
);
|
||||
});
|
||||
|
||||
// ─── List ──────────────────────────────────────────────
|
||||
test("getWebhooks returns an array", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
expect(Array.isArray(webhooks)).toBe(true);
|
||||
});
|
||||
|
||||
test("getWebhooks includes the created webhook", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const found = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(found).toBeDefined();
|
||||
});
|
||||
|
||||
test("getWebhooks shows the webhook as active", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const found = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(found!.is_active).toBe(true);
|
||||
});
|
||||
|
||||
// ─── Update ────────────────────────────────────────────
|
||||
test("updateWebhook returns a success message", async () => {
|
||||
const result = await withRetry(() =>
|
||||
client.updateWebhook({
|
||||
webhookId: createdWebhookId,
|
||||
name: updatedName,
|
||||
url: "https://example.com/updated",
|
||||
eventTypes: [WebhookEvent.MEMORY_DELETED],
|
||||
}),
|
||||
);
|
||||
expect(result.message).toBeDefined();
|
||||
});
|
||||
|
||||
test("updateWebhook persists the new name", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const updated = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(updated!.name).toBe(updatedName);
|
||||
});
|
||||
|
||||
test("updateWebhook persists the new event_types", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const updated = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(updated!.event_types?.sort()).toStrictEqual(
|
||||
[WebhookEvent.MEMORY_DELETED].sort(),
|
||||
);
|
||||
});
|
||||
|
||||
// ─── Delete ────────────────────────────────────────────
|
||||
test("deleteWebhook returns a response", async () => {
|
||||
const result = await withRetry(() =>
|
||||
client.deleteWebhook({ webhookId: createdWebhookId }),
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
test("deleteWebhook removes the webhook from the list", async () => {
|
||||
const webhooks = await withRetry(() => client.getWebhooks());
|
||||
const found = webhooks.find((w) => w.webhook_id === createdWebhookId);
|
||||
expect(found).toBeUndefined();
|
||||
createdWebhookId = "";
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user