/**
 * Regression tests for the impact_score width clamp in pages/news.js.
 *
 * impact_score is documented as 0-10. The width style interpolates the
 * value * 10 to get a percentage, so an out-of-range API response
 * (e.g. 15 or -1) would produce width: 150% or width: -10%. CSS clamps
 * both silently at render time, but the inspected DOM would still show
 * the broken value, and any future code path that read the style back
 * would see the unclamped number.
 *
 * These tests lock in Math.max(0, Math.min(100, ...)) around the width
 * interpolation. They do NOT exercise DOMPurify because the clamp is
 * orthogonal to XSS hardening (covered by news-xss.test.js). The shared
 * render scaffold lives in helpers/news-render-harness.js.
 */

import {
    installNewsRenderHarness,
    makeNewsItem as makeItem,
} from './helpers/news-render-harness.js';

let harness;

beforeAll(async () => {
    harness = await installNewsRenderHarness();
});

function widthForHeadline(headline) {
    const html = harness.capturedHtmlFor(headline);
    if (!html) {
        return null;
    }
    const match = html.match(/width:\s*(\S+)%/);
    return match ? match[1] : null;
}

describe('pages/news.js — impact_score width clamp', () => {
    it('produces width: 50% for a normal impact_score of 5', async () => {
        await harness.renderWith([makeItem({ id: 'a', headline: 'NORMAL_FIVE', impact_score: 5 })]);
        expect(widthForHeadline('NORMAL_FIVE')).toBe('50');
    });

    it('clamps an out-of-range high impact_score to 100% width', async () => {
        // API contract says 0-10, but defend in depth: a buggy response of
        // 15 must not produce width: 150%.
        await harness.renderWith([makeItem({ id: 'b', headline: 'OVER_TEN', impact_score: 15 })]);
        expect(widthForHeadline('OVER_TEN')).toBe('100');
    });

    it('clamps a negative impact_score to 0% width', async () => {
        await harness.renderWith([makeItem({ id: 'c', headline: 'NEGATIVE', impact_score: -3 })]);
        expect(widthForHeadline('NEGATIVE')).toBe('0');
    });

    it('does not affect the impact_score text node (which still shows the raw value)', async () => {
        // The clamp is width-only; the /10 text node shows the real value
        // so the user sees "15/10" and can spot the API bug visually.
        await harness.renderWith([makeItem({
            id: 'd', headline: 'TEXT_UNCLAMPED', impact_score: 15,
        })]);
        const html = harness.capturedHtmlFor('TEXT_UNCLAMPED') || '';
        expect(html).toContain('15/10');
        expect(html).not.toContain('10/10');
    });
});
