never(); } public function test_streamed_xml_escapes_locations_and_has_distinct_url_and_index_elements(): void { $xml = new PublicSitemapXml; $locations = ['https://example.invalid/oportunidades/qa?a=1&b=2']; $document = implode('', iterator_to_array($xml->chunks($locations))); $parsed = new \DOMDocument; $this->assertTrue($parsed->loadXML($document)); $this->assertStringContainsString('&b=2', $document); $this->assertSame($locations[0], $parsed->getElementsByTagName('loc')->item(0)->textContent); $index = implode('', iterator_to_array($xml->chunks($locations, true))); $this->assertStringContainsString('assertStringContainsString('', $index); } public function test_static_sitemap_uses_the_configured_origin_and_contains_no_private_workspace(): void { config(['app.url' => 'https://example.invalid']); $response = app(PublicSitemapController::class)->pages(new PublicSitemapXml); ob_start(); $response->sendContent(); $xml = ob_get_clean(); $this->assertStringContainsString('https://example.invalid/simulador-fiscal', $xml); $this->assertStringContainsString('https://example.invalid/apoio', $xml); $this->assertStringNotContainsString('balcao-virtual', $xml); $this->assertStringNotContainsString('/management', $xml); $this->assertTrue($response->headers->hasCacheControlDirective('no-store')); } public function test_invalid_page_is_refused_before_accessing_the_catalogue(): void { $this->expectException(HttpException::class); app(PublicSitemapController::class)->opportunities('0', new PublicSitemapXml); } public function test_origin_rejects_queries_fragments_credentials_and_non_http_schemes(): void { foreach (['https://example.invalid?q=1', 'https://example.invalid#fragment', 'https://user:pass@example.invalid', 'javascript:alert(1)'] as $base) { config(['app.url' => $base]); try { app(PublicSitemapController::class)->pages(new PublicSitemapXml); $this->fail('Invalid sitemap origin was accepted.'); } catch (HttpException $error) { $this->assertSame(503, $error->getStatusCode()); } } } }