xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmDeletedTest.php (revision 884caed926ca0aa0af6ce3f34ae3aa7317a3361a)
1<?php
2
3namespace dokuwiki\test\Parsing\ParserMode;
4
5use dokuwiki\Parsing\ParserMode\GfmDeleted;
6
7/**
8 * Tests for the GFM strikethrough mode (`~~text~~`).
9 */
10class GfmDeletedTest extends ParserTestBase
11{
12    public function setUp(): void
13    {
14        parent::setUp();
15        $this->setSyntax('md');
16    }
17
18    function testBasicStrikethrough()
19    {
20        $this->P->addMode('gfm_deleted', new GfmDeleted());
21        $this->P->parse('Foo ~~Bar~~ Baz');
22        $calls = [
23            ['document_start', []],
24            ['p_open', []],
25            ['cdata', ["\nFoo "]],
26            ['deleted_open', []],
27            ['cdata', ['Bar']],
28            ['deleted_close', []],
29            ['cdata', [' Baz']],
30            ['p_close', []],
31            ['document_end', []],
32        ];
33        $this->assertCalls($calls, $this->H->calls);
34    }
35
36    function testSingleCharacterBody()
37    {
38        $this->P->addMode('gfm_deleted', new GfmDeleted());
39        $this->P->parse('foo ~~b~~ bar');
40        $calls = [
41            ['document_start', []],
42            ['p_open', []],
43            ['cdata', ["\nfoo "]],
44            ['deleted_open', []],
45            ['cdata', ['b']],
46            ['deleted_close', []],
47            ['cdata', [' bar']],
48            ['p_close', []],
49            ['document_end', []],
50        ];
51        $this->assertCalls($calls, $this->H->calls);
52    }
53
54    function testMultipleWords()
55    {
56        $this->P->addMode('gfm_deleted', new GfmDeleted());
57        $this->P->parse('~~three four five~~');
58        $calls = [
59            ['document_start', []],
60            ['p_open', []],
61            ['cdata', ["\n"]],
62            ['deleted_open', []],
63            ['cdata', ['three four five']],
64            ['deleted_close', []],
65            ['cdata', ['']],
66            ['p_close', []],
67            ['document_end', []],
68        ];
69        $this->assertCalls($calls, $this->H->calls);
70    }
71
72    function testTwoSeparateStrikethroughsOnOneLine()
73    {
74        $this->P->addMode('gfm_deleted', new GfmDeleted());
75        $this->P->parse('~~one~~ and ~~two~~');
76        $calls = [
77            ['document_start', []],
78            ['p_open', []],
79            ['cdata', ["\n"]],
80            ['deleted_open', []],
81            ['cdata', ['one']],
82            ['deleted_close', []],
83            ['cdata', [' and ']],
84            ['deleted_open', []],
85            ['cdata', ['two']],
86            ['deleted_close', []],
87            ['cdata', ['']],
88            ['p_close', []],
89            ['document_end', []],
90        ];
91        $this->assertCalls($calls, $this->H->calls);
92    }
93
94    function testUnmatchedOpenerDoesNotStrike()
95    {
96        $this->P->addMode('gfm_deleted', new GfmDeleted());
97        $this->P->parse('foo ~~bar with no closer');
98        $calls = [
99            ['document_start', []],
100            ['p_open', []],
101            ['cdata', ["\nfoo ~~bar with no closer"]],
102            ['p_close', []],
103            ['document_end', []],
104        ];
105        $this->assertCalls($calls, $this->H->calls);
106    }
107
108    function testOpenerFollowedBySpaceDoesNotStrike()
109    {
110        $this->P->addMode('gfm_deleted', new GfmDeleted());
111        $this->P->parse('foo ~~ bar~~ baz');
112        $calls = [
113            ['document_start', []],
114            ['p_open', []],
115            ['cdata', ["\nfoo ~~ bar~~ baz"]],
116            ['p_close', []],
117            ['document_end', []],
118        ];
119        $this->assertCalls($calls, $this->H->calls);
120    }
121
122    function testEmptyDelimiterDoesNotStrike()
123    {
124        $this->P->addMode('gfm_deleted', new GfmDeleted());
125        $this->P->parse('foo ~~~~ bar');
126        $modes = array_column($this->H->calls, 0);
127        $this->assertNotContains('deleted_open', $modes,
128            'Empty `~~~~` must stay literal');
129    }
130
131    function testTripleTildeDoesNotStrike()
132    {
133        // `~~~` is the GFM fenced-code-block marker; strikethrough must not
134        // consume a run of three or more tildes.
135        $this->P->addMode('gfm_deleted', new GfmDeleted());
136        $this->P->parse('foo ~~~bar~~~ baz');
137        $modes = array_column($this->H->calls, 0);
138        $this->assertNotContains('deleted_open', $modes,
139            'Run of 3+ tildes must not trigger strikethrough');
140    }
141
142    function testMultilineStrikethrough()
143    {
144        $this->P->addMode('gfm_deleted', new GfmDeleted());
145        $this->P->parse("~~line\nline\nline~~");
146        $calls = [
147            ['document_start', []],
148            ['p_open', []],
149            ['cdata', ["\n"]],
150            ['deleted_open', []],
151            ['cdata', ["line\nline\nline"]],
152            ['deleted_close', []],
153            ['cdata', ['']],
154            ['p_close', []],
155            ['document_end', []],
156        ];
157        $this->assertCalls($calls, $this->H->calls);
158    }
159
160    function testDoesNotSpanParagraphBoundary()
161    {
162        // An unclosed `~~` followed by a blank line must stay literal.
163        // Mirrors GFM spec example 492.
164        $this->P->addMode('gfm_deleted', new GfmDeleted());
165        $this->P->parse("This ~~has a\n\nnew paragraph~~.");
166        $modes = array_column($this->H->calls, 0);
167        $this->assertNotContains('deleted_open', $modes,
168            'GfmDeleted must not open when the closing `~~` is past a blank line');
169    }
170
171    function testAllowsSingleNewline()
172    {
173        $this->P->addMode('gfm_deleted', new GfmDeleted());
174        $this->P->parse("~~open\nclose~~");
175        $modes = array_column($this->H->calls, 0);
176        $this->assertContains('deleted_open', $modes,
177            'GfmDeleted must still match across a single newline');
178    }
179
180    function testTrailingWhitespaceBeforeCloserDoesNotStrike()
181    {
182        $this->P->addMode('gfm_deleted', new GfmDeleted());
183        $this->P->parse('~~foo bar ~~');
184        $modes = array_column($this->H->calls, 0);
185        $this->assertNotContains('deleted_open', $modes,
186            'Closer preceded by whitespace must not match');
187    }
188
189    function testSortValue()
190    {
191        $mode = new GfmDeleted();
192        $this->assertSame(130, $mode->getSort());
193    }
194}
195