1*72b2703bSAndreas Gohr<?php 2*72b2703bSAndreas Gohr 3*72b2703bSAndreas Gohrnamespace dokuwiki\test\Parsing\Markdown; 4*72b2703bSAndreas Gohr 5*72b2703bSAndreas Gohrclass SpecReaderTest extends \DokuWikiTest 6*72b2703bSAndreas Gohr{ 7*72b2703bSAndreas Gohr /** Where to write a throwaway fixture. TMP_DIR is created by the test 8*72b2703bSAndreas Gohr * bootstrap and removed by its shutdown handler — no per-test cleanup 9*72b2703bSAndreas Gohr * needed. */ 10*72b2703bSAndreas Gohr private const FIXTURE_PATH = TMP_DIR . '/spec-reader-test.txt'; 11*72b2703bSAndreas Gohr 12*72b2703bSAndreas Gohr private function writeFixture(string $content): SpecReader 13*72b2703bSAndreas Gohr { 14*72b2703bSAndreas Gohr file_put_contents(self::FIXTURE_PATH, $content); 15*72b2703bSAndreas Gohr return new SpecReader(self::FIXTURE_PATH); 16*72b2703bSAndreas Gohr } 17*72b2703bSAndreas Gohr 18*72b2703bSAndreas Gohr public function testSingleOrdinaryExample() 19*72b2703bSAndreas Gohr { 20*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 21*72b2703bSAndreas Gohr## Simple Headings 22*72b2703bSAndreas Gohr 23*72b2703bSAndreas Gohr`````````` example 24*72b2703bSAndreas Gohr# foo 25*72b2703bSAndreas Gohr. 26*72b2703bSAndreas Gohr<h1>foo</h1> 27*72b2703bSAndreas Gohr`````````` 28*72b2703bSAndreas Gohr 29*72b2703bSAndreas Gohrtrailing prose 30*72b2703bSAndreas GohrSPEC); 31*72b2703bSAndreas Gohr 32*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 33*72b2703bSAndreas Gohr $this->assertCount(1, $examples); 34*72b2703bSAndreas Gohr $this->assertSame(1, $examples[0]['number']); 35*72b2703bSAndreas Gohr $this->assertSame('Simple Headings', $examples[0]['section']); 36*72b2703bSAndreas Gohr $this->assertNull($examples[0]['extension']); 37*72b2703bSAndreas Gohr $this->assertSame("# foo", $examples[0]['markdown']); 38*72b2703bSAndreas Gohr $this->assertSame("<h1>foo</h1>", $examples[0]['html']); 39*72b2703bSAndreas Gohr } 40*72b2703bSAndreas Gohr 41*72b2703bSAndreas Gohr public function testSectionTracking() 42*72b2703bSAndreas Gohr { 43*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 44*72b2703bSAndreas Gohr## Section One 45*72b2703bSAndreas Gohr 46*72b2703bSAndreas Gohr`````````` example 47*72b2703bSAndreas Gohra 48*72b2703bSAndreas Gohr. 49*72b2703bSAndreas Gohr<p>a</p> 50*72b2703bSAndreas Gohr`````````` 51*72b2703bSAndreas Gohr 52*72b2703bSAndreas Gohr## Section Two 53*72b2703bSAndreas Gohr 54*72b2703bSAndreas Gohr`````````` example 55*72b2703bSAndreas Gohrb 56*72b2703bSAndreas Gohr. 57*72b2703bSAndreas Gohr<p>b</p> 58*72b2703bSAndreas Gohr`````````` 59*72b2703bSAndreas GohrSPEC); 60*72b2703bSAndreas Gohr 61*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 62*72b2703bSAndreas Gohr $this->assertCount(2, $examples); 63*72b2703bSAndreas Gohr $this->assertSame(1, $examples[0]['number']); 64*72b2703bSAndreas Gohr $this->assertSame('Section One', $examples[0]['section']); 65*72b2703bSAndreas Gohr $this->assertSame(2, $examples[1]['number']); 66*72b2703bSAndreas Gohr $this->assertSame('Section Two', $examples[1]['section']); 67*72b2703bSAndreas Gohr } 68*72b2703bSAndreas Gohr 69*72b2703bSAndreas Gohr public function testExampleWithExtensionLabel() 70*72b2703bSAndreas Gohr { 71*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 72*72b2703bSAndreas Gohr## Tables 73*72b2703bSAndreas Gohr 74*72b2703bSAndreas Gohr`````````` example table 75*72b2703bSAndreas Gohr| a | b | 76*72b2703bSAndreas Gohr| - | - | 77*72b2703bSAndreas Gohr| 1 | 2 | 78*72b2703bSAndreas Gohr. 79*72b2703bSAndreas Gohr<table>…</table> 80*72b2703bSAndreas Gohr`````````` 81*72b2703bSAndreas GohrSPEC); 82*72b2703bSAndreas Gohr 83*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 84*72b2703bSAndreas Gohr $this->assertCount(1, $examples); 85*72b2703bSAndreas Gohr $this->assertSame('table', $examples[0]['extension']); 86*72b2703bSAndreas Gohr $this->assertStringContainsString('| a | b |', $examples[0]['markdown']); 87*72b2703bSAndreas Gohr } 88*72b2703bSAndreas Gohr 89*72b2703bSAndreas Gohr public function testMultilineMarkdownAndHtml() 90*72b2703bSAndreas Gohr { 91*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 92*72b2703bSAndreas Gohr## Multiline 93*72b2703bSAndreas Gohr 94*72b2703bSAndreas Gohr`````````` example 95*72b2703bSAndreas Gohrline one 96*72b2703bSAndreas Gohrline two 97*72b2703bSAndreas Gohr 98*72b2703bSAndreas Gohrline four 99*72b2703bSAndreas Gohr. 100*72b2703bSAndreas Gohr<p>line one 101*72b2703bSAndreas Gohrline two</p> 102*72b2703bSAndreas Gohr<p>line four</p> 103*72b2703bSAndreas Gohr`````````` 104*72b2703bSAndreas GohrSPEC); 105*72b2703bSAndreas Gohr 106*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 107*72b2703bSAndreas Gohr $this->assertSame( 108*72b2703bSAndreas Gohr "line one\nline two\n\nline four", 109*72b2703bSAndreas Gohr $examples[0]['markdown'] 110*72b2703bSAndreas Gohr ); 111*72b2703bSAndreas Gohr $this->assertSame( 112*72b2703bSAndreas Gohr "<p>line one\nline two</p>\n<p>line four</p>", 113*72b2703bSAndreas Gohr $examples[0]['html'] 114*72b2703bSAndreas Gohr ); 115*72b2703bSAndreas Gohr } 116*72b2703bSAndreas Gohr 117*72b2703bSAndreas Gohr public function testBackticksInsideExampleAreNotConfusedForFence() 118*72b2703bSAndreas Gohr { 119*72b2703bSAndreas Gohr // Opening fence is 14 backticks; a shorter run inside must not close. 120*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 121*72b2703bSAndreas Gohr## Code 122*72b2703bSAndreas Gohr 123*72b2703bSAndreas Gohr`````````````` example 124*72b2703bSAndreas Gohrhere is `code` with backticks 125*72b2703bSAndreas Gohr. 126*72b2703bSAndreas Gohr<p>here is <code>code</code> with backticks</p> 127*72b2703bSAndreas Gohr`````````````` 128*72b2703bSAndreas GohrSPEC); 129*72b2703bSAndreas Gohr 130*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 131*72b2703bSAndreas Gohr $this->assertCount(1, $examples); 132*72b2703bSAndreas Gohr $this->assertStringContainsString('`code`', $examples[0]['markdown']); 133*72b2703bSAndreas Gohr } 134*72b2703bSAndreas Gohr 135*72b2703bSAndreas Gohr public function testNumbersAreSequential() 136*72b2703bSAndreas Gohr { 137*72b2703bSAndreas Gohr $body = ''; 138*72b2703bSAndreas Gohr for ($i = 1; $i <= 5; $i++) { 139*72b2703bSAndreas Gohr $body .= "`````````` example\nmd$i\n.\nhtml$i\n``````````\n\n"; 140*72b2703bSAndreas Gohr } 141*72b2703bSAndreas Gohr $reader = $this->writeFixture($body); 142*72b2703bSAndreas Gohr $examples = iterator_to_array($reader->examples(), false); 143*72b2703bSAndreas Gohr $this->assertCount(5, $examples); 144*72b2703bSAndreas Gohr foreach ($examples as $i => $ex) { 145*72b2703bSAndreas Gohr $this->assertSame($i + 1, $ex['number']); 146*72b2703bSAndreas Gohr } 147*72b2703bSAndreas Gohr } 148*72b2703bSAndreas Gohr 149*72b2703bSAndreas Gohr public function testUnclosedFenceThrows() 150*72b2703bSAndreas Gohr { 151*72b2703bSAndreas Gohr $reader = $this->writeFixture(<<<SPEC 152*72b2703bSAndreas Gohr`````````` example 153*72b2703bSAndreas Gohrno closer ever arrives 154*72b2703bSAndreas Gohr. 155*72b2703bSAndreas Gohr<p>x</p> 156*72b2703bSAndreas GohrSPEC); 157*72b2703bSAndreas Gohr $this->expectException(\RuntimeException::class); 158*72b2703bSAndreas Gohr iterator_to_array($reader->examples(), false); 159*72b2703bSAndreas Gohr } 160*72b2703bSAndreas Gohr 161*72b2703bSAndreas Gohr public function testMissingFileThrows() 162*72b2703bSAndreas Gohr { 163*72b2703bSAndreas Gohr $reader = new SpecReader('/nonexistent/path/spec.txt'); 164*72b2703bSAndreas Gohr $this->expectException(\RuntimeException::class); 165*72b2703bSAndreas Gohr iterator_to_array($reader->examples(), false); 166*72b2703bSAndreas Gohr } 167*72b2703bSAndreas Gohr} 168