assertStringMatchesFormat(<<main %d.%dms/%d%index.twig %d.%dms/%d% └ embedded.twig::block(body) └ embedded.twig │ └ included.twig └ index.twig::macro(foo) └ embedded.twigincluded.twig EOF, $dumper->dump($this->getProfile())); } public function testDumpEscapesTemplateAndProfileNames(): void { $root = new Profile('main'); $child = new Profile('', Profile::TEMPLATE); $grandchild = new Profile('', Profile::MACRO, ''); (new \ReflectionProperty($child, 'profiles'))->setValue($child, [$grandchild]); (new \ReflectionProperty($root, 'profiles'))->setValue($root, [$child]); $output = (new HtmlDumper())->dump($root); $this->assertStringNotContainsString('', $output); $this->assertStringNotContainsString('', $output); $this->assertStringNotContainsString('', $output); $this->assertStringContainsString('<img src=x onerror=alert(1)>', $output); $this->assertStringContainsString('<img src=x onerror=alert(2)>', $output); $this->assertStringContainsString('<img src=x onerror=alert(3)>', $output); } public function testDumpEscapesRootProfileName(): void { $root = new Profile('template-name', Profile::ROOT, ''); $output = (new HtmlDumper())->dump($root); $this->assertStringNotContainsString('', $output); $this->assertStringContainsString('<img src=x onerror=alert(1)>', $output); } }