<?php

declare(strict_types=1);

namespace App\Tests\Integration\App;

use App\Tests\Integration\Support\AppTestCase;
use Slim\Views\Twig;
use Twig\Extension\EscaperExtension;

/**
 * SEC_REVIEW F63 — pin Twig's autoescape strategy to `'html'`. The
 * current Twig major defaults to `'html'`, but the SEC_REVIEW asked
 * us not to rely on the default in case a future major bump or a
 * Slim-twig wrapper change silently flips it.
 */
final class TwigConfigTest extends AppTestCase
{
    protected function setUp(): void
    {
        $this->bootApp();
    }

    public function testAutoescapeStrategyIsExplicitlyHtml(): void
    {
        /** @var Twig $twig */
        $twig = $this->container->get(Twig::class);
        $escaper = $twig->getEnvironment()->getExtension(EscaperExtension::class);

        // `getDefaultStrategy` takes the template name; for the
        // pinned `'html'` policy it returns the strategy regardless
        // of name.
        self::assertSame('html', $escaper->getDefaultStrategy('any.twig'));
        self::assertSame('html', $escaper->getDefaultStrategy('pages/login.twig'));
    }

    public function testRenderedTemplateAutoescapesUserInput(): void
    {
        // Defence-in-depth: render a string with a script tag through
        // `{{ value }}` and confirm the output is HTML-escaped. The
        // unit test above pins the configured strategy; this one
        // proves the pipeline actually applies it.
        /** @var Twig $twig */
        $twig = $this->container->get(Twig::class);
        $env = $twig->getEnvironment();

        $env->setLoader(new \Twig\Loader\ArrayLoader([
            'inline.twig' => 'value=[{{ value }}]',
        ]));

        $rendered = $env->render('inline.twig', ['value' => '<script>alert(1)</script>']);

        self::assertSame(
            'value=[&lt;script&gt;alert(1)&lt;/script&gt;]',
            $rendered,
        );
    }
}
