import { test } from 'node:test'; import assert from 'node:assert/strict'; import { CrawlFrontier } from './frontier.js'; test('CrawlFrontier: BFS dequeues in FIFO order, identical to a plain array shift()', () => { const f = new CrawlFrontier('BFS', ['https://a.com/1', 'https://a.com/2']); f.push('https://a.com/3'); assert.equal(f.shift(), 'https://a.com/1'); assert.equal(f.shift(), 'https://a.com/2'); assert.equal(f.shift(), 'https://a.com/3'); assert.equal(f.shift(), undefined); }); test('CrawlFrontier: DFS dequeues in LIFO order', () => { const f = new CrawlFrontier('DFS', ['https://a.com/1', 'https://a.com/2']); f.push('https://a.com/3'); assert.equal(f.shift(), 'https://a.com/3'); assert.equal(f.shift(), 'https://a.com/2'); assert.equal(f.shift(), 'https://a.com/1'); }); test('CrawlFrontier: BEST_FIRST prefers shallower paths over deeper ones', () => { const f = new CrawlFrontier('BEST_FIRST', [ 'https://a.com/products/electronics/phones/model-x', 'https://a.com/about', ]); assert.equal(f.shift(), 'https://a.com/about'); assert.equal(f.shift(), 'https://a.com/products/electronics/phones/model-x'); }); test('CrawlFrontier: BEST_FIRST boosts URLs matching keywords ahead of shallower non-matching ones', () => { const f = new CrawlFrontier('BEST_FIRST', ['https://a.com/'], ['pricing']); f.push('https://a.com/deep/nested/pricing/plans'); // "/" has depth 0 (score 0); the pricing URL has depth 4 (score -4) but +10 for the // keyword match, netting +6 — the keyword-matching page should win despite depth. assert.equal(f.shift(), 'https://a.com/deep/nested/pricing/plans'); assert.equal(f.shift(), 'https://a.com/'); }); test('CrawlFrontier: length reflects push/shift correctly across all strategies', () => { for (const strategy of ['BFS', 'DFS', 'BEST_FIRST'] as const) { const f = new CrawlFrontier(strategy, ['https://a.com/1']); assert.equal(f.length, 1); f.push('https://a.com/2'); assert.equal(f.length, 2); f.shift(); assert.equal(f.length, 1); } }); test('CrawlFrontier: filter returns URLs matching the predicate without mutating the frontier', () => { const f = new CrawlFrontier('BFS', ['https://a.com/1', 'https://a.com/2', 'https://a.com/3']); const matched = f.filter((u) => u.endsWith('/2')); assert.deepEqual(matched, ['https://a.com/2']); assert.equal(f.length, 3); // unchanged }); test('CrawlFrontier: malformed URLs never throw when scored under BEST_FIRST', () => { assert.doesNotThrow(() => { const f = new CrawlFrontier('BEST_FIRST', ['not-a-valid-url', 'https://a.com/ok']); f.shift(); f.shift(); }); });