guides = new GuideRepository(dirname(__DIR__, 2) . '/Fixtures/guides'); } public function testListsTopicsSortedWithoutExtension(): void { self::assertSame(['divi-shortform', 'overview'], $this->guides->topics()); } public function testReturnsMarkdownOfKnownTopic(): void { self::assertStringContainsString('Testinhalt Kurzform', (string) $this->guides->get('divi-shortform')); } /** * @dataProvider maliciousTopics */ public function testRejectsAnythingThatIsNotAPlainTopicName(string $topic): void { self::assertNull($this->guides->get($topic)); } /** @return array */ public static function maliciousTopics(): array { return [ 'traversal' => ['../../wp-config'], 'with extension' => ['overview.md'], 'empty' => [''], 'absolute' => ['/etc/passwd'], 'unknown' => ['does-not-exist'], 'uppercase' => ['OVERVIEW'], ]; } public function testMissingDirectoryYieldsNoTopics(): void { self::assertSame([], (new GuideRepository('/nonexistent/dir'))->topics()); } }