diff --git a/plugins/core/tests/extract.test.ts b/plugins/core/tests/extract.test.ts new file mode 100644 index 0000000..b0c2ad4 --- /dev/null +++ b/plugins/core/tests/extract.test.ts @@ -0,0 +1,53 @@ +import { extractLinks } from '../src/crawler/extract.js'; +import { test, expect, describe, vi, afterEach } from 'vitest'; +import * as cheerio from 'cheerio'; + +vi.mock('cheerio', async (importOriginal) => { + const mod = await importOriginal(); + return { + ...mod, + load: vi.fn((...args: any[]) => mod.load(...args)) + }; +}); + +describe('extractLinks', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + test('should extract links correctly', () => { + const html = ` + + + Foo + Bar + Baz + Top + + + `; + const links = extractLinks(html, 'https://example.com/page/'); + expect(links).toContain('https://example.com/foo'); + expect(links).toContain('https://example.com/page/bar'); + expect(links).toContain('https://other.com/baz'); + expect(links).not.toContain('https://example.com/page/#top'); + expect(links).toContain('https://example.com/page/'); + }); + + test('should handle cheerio errors gracefully', () => { + const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { }); + const error = new Error('Cheerio error'); + + vi.mocked(cheerio.load).mockImplementationOnce(() => { + throw error; + }); + + const links = extractLinks('', 'https://example.com'); + + expect(links).toEqual([]); + expect(consoleSpy).toHaveBeenCalledWith( + expect.stringContaining('Error extracting links from https://example.com'), + error + ); + }); +}); diff --git a/plugins/core/tests/normalize.test.ts b/plugins/core/tests/normalize.test.ts index f1bb9f8..45aee3e 100644 --- a/plugins/core/tests/normalize.test.ts +++ b/plugins/core/tests/normalize.test.ts @@ -1,5 +1,4 @@ import { normalizeUrl } from '../src/crawler/normalize.js'; -import { extractLinks } from '../src/crawler/extract.js'; import { test, expect } from 'vitest'; test('normalizeUrl', () => { @@ -11,24 +10,6 @@ test('normalizeUrl', () => { expect(normalizeUrl('https://example.com/', '')).toBe('https://example.com/'); }); -test('extractLinks', () => { - const html = ` - - - Foo - Bar - Baz - Top - - - `; - const links = extractLinks(html, 'https://example.com/page/'); - expect(links).toContain('https://example.com/foo'); - expect(links).toContain('https://example.com/page/bar'); - expect(links).toContain('https://other.com/baz'); - expect(links).not.toContain('https://example.com/page/#top'); - expect(links).toContain('https://example.com/page/'); // #top resolves to base url without fragment -}); test('normalizeUrl: absolute resolution', () => { expect(normalizeUrl('/foo', 'https://example.com')).toBe('https://example.com/foo'); expect(normalizeUrl('bar', 'https://example.com/baz/')).toBe('https://example.com/baz/bar');