Files
noteflow/client/e2e-native/webhooks.spec.ts
2026-01-14 23:23:01 -05:00

336 lines
10 KiB
TypeScript

/**
* Webhook E2E Tests
*
* Tests for webhook CRUD operations.
*/
/// <reference path="./globals.d.ts" />
import { waitForAppReady, TestData } from './fixtures';
describe('Webhook Operations', () => {
let testWebhookId: string | null = null;
let testWorkspaceId: string | null = null;
before(async () => {
await waitForAppReady();
// Get a workspace ID for webhook operations
const workspaces = await browser.execute(async () => {
const api = window.__NOTEFLOW_API__;
try {
const response = await api?.listWorkspaces();
return response?.workspaces ?? [];
} catch {
return [];
}
});
// Only use workspace if it has a valid (non-null) ID
const nullUuid = '00000000-0000-0000-0000-000000000000';
if (workspaces.length > 0 && workspaces[0].id && workspaces[0].id !== nullUuid) {
testWorkspaceId = workspaces[0].id;
}
});
after(async () => {
if (testWebhookId) {
try {
await browser.execute(async (id) => {
const api = window.__NOTEFLOW_API__;
await api?.deleteWebhook(id);
}, testWebhookId);
} catch {
// Ignore cleanup errors
}
}
});
describe('registerWebhook', () => {
it('should register a new webhook', async () => {
if (!testWorkspaceId) {
// Skip test - no workspace available
return;
}
const testId = TestData.generateTestId();
const result = await browser.execute(
async (id, workspaceId) => {
const api = window.__NOTEFLOW_API__;
try {
const webhook = await api?.registerWebhook({
workspace_id: workspaceId,
url: `https://example.com/webhook/${id}`,
events: ['meeting.completed'],
name: `Test Webhook ${id}`,
});
return { success: true, webhook };
} catch (e: unknown) {
const error = e as { message?: string; error?: string };
const errorMsg =
error?.message ||
error?.error ||
(typeof e === 'object' ? JSON.stringify(e) : String(e));
return { success: false, error: errorMsg };
}
},
testId,
testWorkspaceId
);
expect(result).toBeDefined();
if (result.success) {
expect(result.webhook).toHaveProperty('id');
expect(result.webhook).toHaveProperty('url');
expect(result.webhook).toHaveProperty('events');
testWebhookId = result.webhook?.id ?? null;
}
});
it('should register webhook with multiple events', async () => {
if (!testWorkspaceId) {
// Skip test - no workspace available
return;
}
const testId = TestData.generateTestId();
const result = await browser.execute(
async (id, workspaceId) => {
const api = window.__NOTEFLOW_API__;
try {
const webhook = await api?.registerWebhook({
workspace_id: workspaceId,
url: `https://example.com/webhook/${id}`,
events: ['meeting.completed', 'summary.generated', 'recording.started'],
name: `Multi-Event Webhook ${id}`,
});
return { success: true, webhook };
} catch (e: unknown) {
const error = e as { message?: string; error?: string };
const errorMsg =
error?.message ||
error?.error ||
(typeof e === 'object' ? JSON.stringify(e) : String(e));
return { success: false, error: errorMsg };
}
},
testId,
testWorkspaceId
);
expect(result).toBeDefined();
if (result.success) {
expect(result.webhook?.events?.length).toBe(3);
// Cleanup
if (result.webhook?.id) {
await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
await api?.deleteWebhook(webhookId);
}, result.webhook.id);
}
}
});
it('should register webhook with secret', async () => {
if (!testWorkspaceId) {
// Skip test - no workspace available
return;
}
const testId = TestData.generateTestId();
const result = await browser.execute(
async (id, workspaceId) => {
const api = window.__NOTEFLOW_API__;
try {
const webhook = await api?.registerWebhook({
workspace_id: workspaceId,
url: `https://example.com/webhook/${id}`,
events: ['meeting.completed'],
name: `Secret Webhook ${id}`,
secret: 'my-webhook-secret',
});
return { success: true, webhook };
} catch (e: unknown) {
const error = e as { message?: string; error?: string };
const errorMsg =
error?.message ||
error?.error ||
(typeof e === 'object' ? JSON.stringify(e) : String(e));
return { success: false, error: errorMsg };
}
},
testId,
testWorkspaceId
);
expect(result).toBeDefined();
if (result.success && result.webhook?.id) {
// Cleanup
await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
await api?.deleteWebhook(webhookId);
}, result.webhook.id);
}
});
});
describe('listWebhooks', () => {
it('should list all webhooks', async () => {
const result = await browser.execute(async () => {
const api = window.__NOTEFLOW_API__;
try {
const response = await api?.listWebhooks();
return { success: true, ...response };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
});
expect(result).toBeDefined();
if (result.success) {
expect(result).toHaveProperty('webhooks');
expect(Array.isArray(result.webhooks)).toBe(true);
}
});
it('should list only enabled webhooks', async () => {
const result = await browser.execute(async () => {
const api = window.__NOTEFLOW_API__;
try {
const response = await api?.listWebhooks(true);
return { success: true, ...response };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
});
expect(result).toBeDefined();
if (result.success && result.webhooks) {
for (const webhook of result.webhooks) {
expect(webhook.enabled).toBe(true);
}
}
});
});
describe('updateWebhook', () => {
it('should update webhook name', async () => {
if (!testWebhookId) {
// Skip test - no test webhook created
return;
}
const result = await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
try {
const updated = await api?.updateWebhook({
webhook_id: webhookId,
name: 'Updated Webhook Name',
});
return { success: true, updated };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
}, testWebhookId);
expect(result).toBeDefined();
if (result.success) {
expect(result.updated?.name).toBe('Updated Webhook Name');
}
});
it('should disable webhook', async () => {
if (!testWebhookId) {
// Skip test - no test webhook created
return;
}
const result = await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
try {
const updated = await api?.updateWebhook({
webhook_id: webhookId,
enabled: false,
});
return { success: true, updated };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
}, testWebhookId);
expect(result).toBeDefined();
if (result.success) {
expect(result.updated?.enabled).toBe(false);
}
});
});
describe('getWebhookDeliveries', () => {
it('should get delivery history', async () => {
if (!testWebhookId) {
// Skip test - no test webhook created
return;
}
const result = await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
try {
const response = await api?.getWebhookDeliveries(webhookId, 10);
return { success: true, ...response };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
}, testWebhookId);
expect(result).toBeDefined();
if (result.success) {
expect(result).toHaveProperty('deliveries');
}
});
});
describe('deleteWebhook', () => {
it('should delete a webhook', async () => {
if (!testWorkspaceId) {
// Skip test - no workspace available
return;
}
// Create a webhook to delete
const testId = TestData.generateTestId();
const createResult = await browser.execute(
async (id, workspaceId) => {
const api = window.__NOTEFLOW_API__;
try {
return await api?.registerWebhook({
workspace_id: workspaceId,
url: `https://example.com/delete/${id}`,
events: ['meeting.completed'],
name: `Delete Test ${id}`,
});
} catch {
return null;
}
},
testId,
testWorkspaceId
);
if (createResult?.id) {
const deleteResult = await browser.execute(async (webhookId) => {
const api = window.__NOTEFLOW_API__;
try {
const response = await api?.deleteWebhook(webhookId);
return { success: true, ...response };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}
}, createResult.id);
expect(deleteResult.success).toBe(true);
}
});
});
});