const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const { extractPrice, fetchAndExtractPrice } = require('../src/scraper'); function loadFixture(name) { return fs.readFileSync(path.join(__dirname, 'fixtures', name), 'utf8'); } test('extractPrice reads price from JSON-LD Product offers', () => { const result = extractPrice(loadFixture('json-ld.html')); assert.deepEqual(result, { price: 19.99, method: 'json-ld' }); }); test('extractPrice reads price from og:price:amount meta tag', () => { const result = extractPrice(loadFixture('meta-tag.html')); assert.deepEqual(result, { price: 24.50, method: 'meta' }); }); test('extractPrice falls back to euro-amount regex in page text', () => { const result = extractPrice(loadFixture('regex-fallback.html')); assert.deepEqual(result, { price: 14.95, method: 'regex' }); }); test('extractPrice returns null price when nothing matches', () => { const result = extractPrice(loadFixture('no-price.html')); assert.deepEqual(result, { price: null, method: null }); }); test('fetchAndExtractPrice returns error when fetch rejects', async () => { const fetchImpl = async () => { throw new Error('network down'); }; const result = await fetchAndExtractPrice('https://example.invalid', { fetchImpl }); assert.equal(result.price, null); assert.ok(result.error instanceof Error); }); test('fetchAndExtractPrice returns error on non-OK response', async () => { const fetchImpl = async () => ({ ok: false, status: 404, text: async () => '' }); const result = await fetchAndExtractPrice('https://example.invalid', { fetchImpl }); assert.equal(result.price, null); assert.ok(result.error instanceof Error); }); test('fetchAndExtractPrice extracts price from fetched HTML', async () => { const html = loadFixture('meta-tag.html'); const fetchImpl = async () => ({ ok: true, status: 200, text: async () => html }); const result = await fetchAndExtractPrice('https://example.invalid', { fetchImpl }); assert.deepEqual(result, { price: 24.50, method: 'meta', error: null }); });