import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { fetchUrl } from '../src/fetcher.js';
import puppeteer from 'puppeteer';
// Mock puppeteer
vi.mock('puppeteer');
describe('fetchUrl', () => {
let mockBrowser: any;
let mockPage: any;
beforeEach(() => {
// Reset mocks before each test
vi.clearAllMocks();
mockPage = {
goto: vi.fn().mockResolvedValue(undefined),
content: vi.fn().mockResolvedValue(''),
};
mockBrowser = {
newPage: vi.fn().mockResolvedValue(mockPage),
close: vi.fn().mockResolvedValue(undefined),
};
(puppeteer.launch as any).mockResolvedValue(mockBrowser);
});
it('should fetch and parse HTML content', async () => {
const mockHtml = `
<html>
<head><title>Test Page</title></head>
<body>
<article>
<h1>Article Title</h1>
<p>This is the main content.</p>
<script>console.log('Should be removed')</script>
</article>
</body>
</html>
`;
mockPage.content.mockResolvedValue(mockHtml);
const result = await fetchUrl('https://example.com');
expect(puppeteer.launch).toHaveBeenCalledWith({ headless: true });
expect(mockBrowser.newPage).toHaveBeenCalled();
expect(mockPage.goto).toHaveBeenCalledWith('https://example.com', { waitUntil: 'networkidle0' });
expect(mockPage.content).toHaveBeenCalled();
expect(mockBrowser.close).toHaveBeenCalled();
expect(result.title).toBe('Test Page');
expect(result.content).toContain('This is the main content.');
expect(result.content).not.toContain('Should be removed');
expect(result.url).toBe('https://example.com');
});
it('should throw error on failed navigation', async () => {
const error = new Error('Navigation failed');
mockPage.goto.mockRejectedValue(error);
await expect(fetchUrl('https://example.com/fail')).rejects.toThrow('Navigation failed');
expect(mockBrowser.close).toHaveBeenCalled();
});
});