UNPKG

mcp-crawl4ai-ts

Version:

TypeScript MCP server for Crawl4AI - web crawling and content extraction

242 lines 10.7 kB
import { createTestClient, cleanupTestClient, TEST_TIMEOUTS } from './test-utils.js'; describe('Session Management Integration Tests', () => { let client; const createdSessions = []; beforeAll(async () => { client = await createTestClient(); }, TEST_TIMEOUTS.medium); afterEach(async () => { // Clean up any sessions created during tests for (const sessionId of createdSessions) { try { await client.callTool({ name: 'clear_session', arguments: { session_id: sessionId }, }); } catch (e) { // Ignore errors during cleanup console.debug('Cleanup error:', e); } } createdSessions.length = 0; }); afterAll(async () => { if (client) { await cleanupTestClient(client); } }); describe('create_session', () => { it('should create session with auto-generated ID', async () => { const result = await client.callTool({ name: 'create_session', arguments: {}, }); expect(result).toBeDefined(); const typedResult = result; expect(typedResult.content).toBeDefined(); expect(Array.isArray(typedResult.content)).toBe(true); const textContent = typedResult.content.find((c) => c.type === 'text'); expect(textContent).toBeDefined(); expect(textContent?.text).toContain('Session created successfully'); // Check returned parameters expect(typedResult.session_id).toBeDefined(); expect(typedResult.session_id).toMatch(/^session-/); expect(typedResult.browser_type).toBe('chromium'); expect(typedResult.initial_url).toBeUndefined(); expect(typedResult.created_at).toBeDefined(); // Track for cleanup createdSessions.push(typedResult.session_id); }, TEST_TIMEOUTS.short); it('should create session with custom ID', async () => { const customId = `test-session-${Date.now()}`; const result = await client.callTool({ name: 'create_session', arguments: { session_id: customId, }, }); const typedResult = result; expect(typedResult.session_id).toBe(customId); expect(typedResult.browser_type).toBe('chromium'); // Track for cleanup createdSessions.push(customId); }, TEST_TIMEOUTS.short); it('should create session with initial URL', async () => { const result = await client.callTool({ name: 'create_session', arguments: { initial_url: 'https://example.com', browser_type: 'chromium', }, }); const typedResult = result; expect(typedResult.session_id).toBeDefined(); expect(typedResult.browser_type).toBe('chromium'); expect(typedResult.initial_url).toBe('https://example.com'); const textContent = typedResult.content.find((c) => c.type === 'text'); expect(textContent?.text).toContain('Pre-warmed with: https://example.com'); // Track for cleanup createdSessions.push(typedResult.session_id); }, TEST_TIMEOUTS.medium); }); describe('list_sessions', () => { it('should list all active sessions', async () => { // Create a few sessions const session1 = await client.callTool({ name: 'create_session', arguments: {}, }); const session2 = await client.callTool({ name: 'create_session', arguments: { initial_url: 'https://example.com', }, }); // List sessions const result = await client.callTool({ name: 'list_sessions', arguments: {}, }); expect(result).toBeDefined(); const content = result.content; const textContent = content.find((c) => c.type === 'text'); expect(textContent).toBeDefined(); expect(textContent?.text).toContain('Active sessions (2):'); expect(textContent?.text).toContain(session1.session_id); expect(textContent?.text).toContain(session2.session_id); // Track for cleanup createdSessions.push(session1.session_id); createdSessions.push(session2.session_id); }, TEST_TIMEOUTS.short); it('should show empty list when no sessions', async () => { // First, clear any existing sessions const listResult = await client.callTool({ name: 'list_sessions', arguments: {}, }); // Parse existing sessions and clear them const listText = listResult.content.find((c) => c.type === 'text')?.text || ''; if (!listText.includes('No active sessions')) { // Extract session IDs from the list const sessionIdMatches = listText.match(/- (session-[\w-]+|test-session-[\w-]+|lifecycle-test)/g); if (sessionIdMatches) { for (const match of sessionIdMatches) { const sessionId = match.substring(2); // Remove "- " prefix await client.callTool({ name: 'clear_session', arguments: { session_id: sessionId }, }); } } } // Now check for empty list const result = await client.callTool({ name: 'list_sessions', arguments: {}, }); const content = result.content; const textContent = content.find((c) => c.type === 'text'); expect(textContent?.text).toContain('No active sessions'); }, TEST_TIMEOUTS.short); }); describe('clear_session', () => { it('should clear existing session', async () => { // Create a session const createResult = await client.callTool({ name: 'create_session', arguments: {}, }); const sessionId = createResult.session_id; // Clear it const clearResult = await client.callTool({ name: 'clear_session', arguments: { session_id: sessionId }, }); const content = clearResult.content; const textContent = content.find((c) => c.type === 'text'); expect(textContent?.text).toContain('Session cleared successfully'); expect(textContent?.text).toContain(sessionId); // Verify it's gone const listResult = await client.callTool({ name: 'list_sessions', arguments: {}, }); const listContent = listResult.content; const listText = listContent.find((c) => c.type === 'text'); expect(listText?.text).not.toContain(sessionId); }, TEST_TIMEOUTS.short); it('should handle clearing non-existent session', async () => { const result = await client.callTool({ name: 'clear_session', arguments: { session_id: 'non-existent-session' }, }); const content = result.content; const textContent = content.find((c) => c.type === 'text'); expect(textContent?.text).toContain('Session not found'); }, TEST_TIMEOUTS.short); }); describe('Session lifecycle', () => { it('should support full session lifecycle', async () => { // 1. Create session const createResult = await client.callTool({ name: 'create_session', arguments: { session_id: 'lifecycle-test', initial_url: 'https://example.com', browser_type: 'chromium', }, }); const sessionId = createResult.session_id; expect(sessionId).toBe('lifecycle-test'); // 2. List sessions (should include our session) const listResult = await client.callTool({ name: 'list_sessions', arguments: {}, }); const listText = listResult.content.find((c) => c.type === 'text')?.text; expect(listText).toContain('lifecycle-test'); expect(listText).toContain('chromium'); // 3. Use the session with crawl tool const crawlResult = await client.callTool({ name: 'crawl', arguments: { url: 'https://example.com/test', session_id: sessionId, }, }); expect(crawlResult).toBeDefined(); // 4. Clear session const clearResult = await client.callTool({ name: 'clear_session', arguments: { session_id: sessionId }, }); const clearText = clearResult.content.find((c) => c.type === 'text')?.text; expect(clearText).toContain('Session cleared successfully'); // 5. Verify it's gone const finalListResult = await client.callTool({ name: 'list_sessions', arguments: {}, }); const finalListText = finalListResult.content.find((c) => c.type === 'text')?.text; expect(finalListText).not.toContain('lifecycle-test'); }, TEST_TIMEOUTS.long); }); describe('Error handling', () => { it('should handle invalid initial_url', async () => { const result = await client.callTool({ name: 'create_session', arguments: { initial_url: 'not-a-url', }, }); expect(result).toBeDefined(); const content = result.content; const textContent = content.find((c) => c.type === 'text'); expect(textContent).toBeDefined(); expect(textContent?.text).toContain('Error'); expect(textContent?.text?.toLowerCase()).toContain('invalid'); }, TEST_TIMEOUTS.short); }); }); //# sourceMappingURL=session-management.integration.test.js.map