xref: /dokuwiki/_test/tests/Parsing/ParserMode/ParserTestBase.php (revision 504c13e8df88563c11b3720b317991bc38835a35)
1*504c13e8SAndreas Gohr<?php
2*504c13e8SAndreas Gohr
3*504c13e8SAndreas Gohrnamespace dokuwiki\test\Parsing\ParserMode;
4*504c13e8SAndreas Gohr
5*504c13e8SAndreas Gohruse dokuwiki\Parsing\Handler;
6*504c13e8SAndreas Gohruse dokuwiki\Parsing\Parser;
7*504c13e8SAndreas Gohr
8*504c13e8SAndreas Gohr/**
9*504c13e8SAndreas Gohr * Base class for parser mode tests
10*504c13e8SAndreas Gohr *
11*504c13e8SAndreas Gohr * Sets up a fresh Parser and Handler for each test. Provides assertion helpers
12*504c13e8SAndreas Gohr * for comparing handler call sequences.
13*504c13e8SAndreas Gohr */
14*504c13e8SAndreas Gohrabstract class ParserTestBase extends \DokuWikiTest
15*504c13e8SAndreas Gohr{
16*504c13e8SAndreas Gohr    /** @var Parser parser instance for the current test */
17*504c13e8SAndreas Gohr    protected Parser $P;
18*504c13e8SAndreas Gohr    /** @var Handler handler instance that records calls made by the parser */
19*504c13e8SAndreas Gohr    protected Handler $H;
20*504c13e8SAndreas Gohr
21*504c13e8SAndreas Gohr    /** @inheritdoc */
22*504c13e8SAndreas Gohr    public function setUp(): void
23*504c13e8SAndreas Gohr    {
24*504c13e8SAndreas Gohr        parent::setUp();
25*504c13e8SAndreas Gohr        $this->H = new Handler();
26*504c13e8SAndreas Gohr        $this->P = new Parser($this->H);
27*504c13e8SAndreas Gohr    }
28*504c13e8SAndreas Gohr
29*504c13e8SAndreas Gohr    /** @inheritdoc */
30*504c13e8SAndreas Gohr    public function tearDown(): void
31*504c13e8SAndreas Gohr    {
32*504c13e8SAndreas Gohr        unset($this->P, $this->H);
33*504c13e8SAndreas Gohr        parent::tearDown();
34*504c13e8SAndreas Gohr    }
35*504c13e8SAndreas Gohr
36*504c13e8SAndreas Gohr    /**
37*504c13e8SAndreas Gohr     * Assert that handler calls match the expected calls, ignoring byte index positions
38*504c13e8SAndreas Gohr     *
39*504c13e8SAndreas Gohr     * The byte index (element [2] in each call) is stripped before comparison because
40*504c13e8SAndreas Gohr     * it depends on internal parser state and is not relevant for most tests.
41*504c13e8SAndreas Gohr     *
42*504c13e8SAndreas Gohr     * @param array $expected the expected call sequence
43*504c13e8SAndreas Gohr     * @param array $actual the actual handler calls (typically $this->H->calls)
44*504c13e8SAndreas Gohr     * @param string $message optional failure message
45*504c13e8SAndreas Gohr     */
46*504c13e8SAndreas Gohr    protected function assertCalls(array $expected, array $actual, string $message = ''): void
47*504c13e8SAndreas Gohr    {
48*504c13e8SAndreas Gohr        $this->assertEquals($expected, array_map($this->stripByteIndex(...), $actual), $message);
49*504c13e8SAndreas Gohr    }
50*504c13e8SAndreas Gohr
51*504c13e8SAndreas Gohr    /**
52*504c13e8SAndreas Gohr     * Remove the byte index from a single handler call
53*504c13e8SAndreas Gohr     *
54*504c13e8SAndreas Gohr     * Recursively processes nested calls (e.g. footnotes).
55*504c13e8SAndreas Gohr     *
56*504c13e8SAndreas Gohr     * @param array $call a single handler call [method, args, byteindex]
57*504c13e8SAndreas Gohr     * @return array the call with the byte index removed
58*504c13e8SAndreas Gohr     */
59*504c13e8SAndreas Gohr    private function stripByteIndex(array $call): array
60*504c13e8SAndreas Gohr    {
61*504c13e8SAndreas Gohr        unset($call[2]);
62*504c13e8SAndreas Gohr        if ($call[0] === 'nest') {
63*504c13e8SAndreas Gohr            $call[1][0] = array_map($this->stripByteIndex(...), $call[1][0]);
64*504c13e8SAndreas Gohr        }
65*504c13e8SAndreas Gohr        return $call;
66*504c13e8SAndreas Gohr    }
67*504c13e8SAndreas Gohr}
68