xref: /dokuwiki/_test/tests/File/PageResolverTest.php (revision 98640fd3947e9ff996e1c9206b5f845465794486)
1*98640fd3SAndreas Gohr<?php
2*98640fd3SAndreas Gohr
3*98640fd3SAndreas Gohrnamespace dokuwiki\test\File;
4*98640fd3SAndreas Gohr
5*98640fd3SAndreas Gohruse dokuwiki\File\PageResolver;
6*98640fd3SAndreas Gohr
7*98640fd3SAndreas Gohr/**
8*98640fd3SAndreas Gohr * @todo tests that make use of revisions might be wanted
9*98640fd3SAndreas Gohr */
10*98640fd3SAndreas Gohrclass PageResolverTest extends \DokuWikiTest
11*98640fd3SAndreas Gohr{
12*98640fd3SAndreas Gohr    /**
13*98640fd3SAndreas Gohr     * @return \Generator|array
14*98640fd3SAndreas Gohr     * @see testResolveID
15*98640fd3SAndreas Gohr     */
16*98640fd3SAndreas Gohr    public function provideResolveData()
17*98640fd3SAndreas Gohr    {
18*98640fd3SAndreas Gohr        $data = [
19*98640fd3SAndreas Gohr            // relative current in root
20*98640fd3SAndreas Gohr            ['context', 'page', 'page'],
21*98640fd3SAndreas Gohr            ['context', '.page', 'page'],
22*98640fd3SAndreas Gohr            ['context', '.:page', 'page'],
23*98640fd3SAndreas Gohr
24*98640fd3SAndreas Gohr            // relative current in namespace
25*98640fd3SAndreas Gohr            ['lev1:lev2:context', 'page', 'lev1:lev2:page'],
26*98640fd3SAndreas Gohr            ['lev1:lev2:context', '.page', 'lev1:lev2:page'],
27*98640fd3SAndreas Gohr            ['lev1:lev2:context', '.:page', 'lev1:lev2:page'],
28*98640fd3SAndreas Gohr
29*98640fd3SAndreas Gohr            // relative upper in root
30*98640fd3SAndreas Gohr            ['context', '..page', 'page'],
31*98640fd3SAndreas Gohr            ['context', '..:page', 'page'],
32*98640fd3SAndreas Gohr
33*98640fd3SAndreas Gohr            // relative upper in namespace
34*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..page', 'lev1:page'],
35*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:page', 'lev1:page'],
36*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:..:page', 'page'],
37*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:..:..:page', 'page'],
38*98640fd3SAndreas Gohr
39*98640fd3SAndreas Gohr            // deeper nesting
40*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..page', 'lev1:lev2:page'],
41*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:page', 'lev1:lev2:page'],
42*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..page', 'lev1:page'],
43*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..:page', 'lev1:page'],
44*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..:..page', 'page'],
45*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..:..:page', 'page'],
46*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..:..:..page', 'page'],
47*98640fd3SAndreas Gohr            ['lev1:lev2:lev3:context', '..:..:..:..:page', 'page'],
48*98640fd3SAndreas Gohr
49*98640fd3SAndreas Gohr            // strange and broken ones
50*98640fd3SAndreas Gohr            ['lev1:lev2:context', '....:....:page', 'lev1:lev2:page'],
51*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:..:lev3:page', 'lev3:page'],
52*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:..:lev3:..:page', 'page'],
53*98640fd3SAndreas Gohr            ['lev1:lev2:context', '..:..:lev3:..:page:....:...', 'page'],
54*98640fd3SAndreas Gohr
55*98640fd3SAndreas Gohr            // relative to current page
56*98640fd3SAndreas Gohr            ['context', '~page', 'context:page'],
57*98640fd3SAndreas Gohr            ['context', '~:page', 'context:page'],
58*98640fd3SAndreas Gohr            ['lev1:lev2:context', '~page', 'lev1:lev2:context:page'],
59*98640fd3SAndreas Gohr            ['lev1:lev2:context', '~:page', 'lev1:lev2:context:page'],
60*98640fd3SAndreas Gohr
61*98640fd3SAndreas Gohr            // start pages
62*98640fd3SAndreas Gohr            ['context', '.:', 'start'],
63*98640fd3SAndreas Gohr            ['foo:context', '.:', 'foo:start'],
64*98640fd3SAndreas Gohr            ['context', 'foo:', 'foo:start'],
65*98640fd3SAndreas Gohr            ['foo:context', 'foo:', 'foo:start'],
66*98640fd3SAndreas Gohr            ['context', '~foo:', 'context:foo:start'],
67*98640fd3SAndreas Gohr            ['foo:context', '~foo:', 'foo:context:foo:start'],
68*98640fd3SAndreas Gohr
69*98640fd3SAndreas Gohr            // empty page links to itself
70*98640fd3SAndreas Gohr            ['context', '', 'context'],
71*98640fd3SAndreas Gohr            ['foo:context', '', 'foo:context'],
72*98640fd3SAndreas Gohr        ];
73*98640fd3SAndreas Gohr
74*98640fd3SAndreas Gohr        // run each test without a hash
75*98640fd3SAndreas Gohr        foreach ($data as $row) {
76*98640fd3SAndreas Gohr            yield $row;
77*98640fd3SAndreas Gohr        }
78*98640fd3SAndreas Gohr
79*98640fd3SAndreas Gohr        // run each test with a hash
80*98640fd3SAndreas Gohr        foreach ($data as $row) {
81*98640fd3SAndreas Gohr            $row[1] .= '#somehash';
82*98640fd3SAndreas Gohr            $row[2] .= '#somehash';
83*98640fd3SAndreas Gohr            yield $row;
84*98640fd3SAndreas Gohr        }
85*98640fd3SAndreas Gohr    }
86*98640fd3SAndreas Gohr
87*98640fd3SAndreas Gohr    /**
88*98640fd3SAndreas Gohr     * @dataProvider provideResolveData
89*98640fd3SAndreas Gohr     * @param string $context
90*98640fd3SAndreas Gohr     * @param string $id
91*98640fd3SAndreas Gohr     * @param string $expected
92*98640fd3SAndreas Gohr     */
93*98640fd3SAndreas Gohr    public function testResolveID($context, $id, $expected)
94*98640fd3SAndreas Gohr    {
95*98640fd3SAndreas Gohr        $resolver = new PageResolver($context);
96*98640fd3SAndreas Gohr        $this->assertEquals($expected, $resolver->resolveId($id));
97*98640fd3SAndreas Gohr    }
98*98640fd3SAndreas Gohr
99*98640fd3SAndreas Gohr    /**
100*98640fd3SAndreas Gohr     * Tilde start page bahaviour
101*98640fd3SAndreas Gohr     *
102*98640fd3SAndreas Gohr     * Please note that a ~ alone is the same as ~:
103*98640fd3SAndreas Gohr     */
104*98640fd3SAndreas Gohr    public function testTildeStartPage()
105*98640fd3SAndreas Gohr    {
106*98640fd3SAndreas Gohr        $context = 'foo:context';
107*98640fd3SAndreas Gohr        $resolver = new PageResolver($context);
108*98640fd3SAndreas Gohr
109*98640fd3SAndreas Gohr        // the $context page itself does not exist
110*98640fd3SAndreas Gohr        // a link like that is usually not possible, but we fall back to standard start
111*98640fd3SAndreas Gohr        // page behaviour
112*98640fd3SAndreas Gohr        $this->assertEquals("$context:start", $resolver->resolveId('~:'));
113*98640fd3SAndreas Gohr        $this->assertEquals("$context:start", $resolver->resolveId('~'));
114*98640fd3SAndreas Gohr
115*98640fd3SAndreas Gohr        // now $context has become the start page
116*98640fd3SAndreas Gohr        saveWikiText($context, 'test', 'test');
117*98640fd3SAndreas Gohr        $this->assertEquals($context, $resolver->resolveId('~:'));
118*98640fd3SAndreas Gohr
119*98640fd3SAndreas Gohr        // now we have a startpage named like the namespace
120*98640fd3SAndreas Gohr        saveWikiText("$context:context", 'test', 'test');
121*98640fd3SAndreas Gohr        $this->assertEquals("$context:context", $resolver->resolveId('~:'));
122*98640fd3SAndreas Gohr        $this->assertEquals("$context:context", $resolver->resolveId('~'));
123*98640fd3SAndreas Gohr
124*98640fd3SAndreas Gohr        // now we have a dedicated start page
125*98640fd3SAndreas Gohr        saveWikiText("$context:start", 'test', 'test');
126*98640fd3SAndreas Gohr        $this->assertEquals("$context:start", $resolver->resolveId('~:'));
127*98640fd3SAndreas Gohr        $this->assertEquals("$context:start", $resolver->resolveId('~'));
128*98640fd3SAndreas Gohr    }
129*98640fd3SAndreas Gohr
130*98640fd3SAndreas Gohr    public function testResolveStartPage()
131*98640fd3SAndreas Gohr    {
132*98640fd3SAndreas Gohr
133*98640fd3SAndreas Gohr        $resolver = new PageResolver('arbitrary');
134*98640fd3SAndreas Gohr
135*98640fd3SAndreas Gohr        $expect = 'foo:start';
136*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]);
137*98640fd3SAndreas Gohr        $this->assertEquals($expect, $actual, 'default non-existing');
138*98640fd3SAndreas Gohr
139*98640fd3SAndreas Gohr        saveWikiText('foo', 'test', 'test');
140*98640fd3SAndreas Gohr        $expect = 'foo';
141*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]);
142*98640fd3SAndreas Gohr        $this->assertEquals($expect, $actual, 'page like namespace outside');
143*98640fd3SAndreas Gohr
144*98640fd3SAndreas Gohr        saveWikiText('foo:foo', 'test', 'test');
145*98640fd3SAndreas Gohr        $expect = 'foo:foo';
146*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]);
147*98640fd3SAndreas Gohr        $this->assertEquals($expect, $actual, 'page like namespace inside');
148*98640fd3SAndreas Gohr
149*98640fd3SAndreas Gohr        saveWikiText('foo:start', 'test', 'test');
150*98640fd3SAndreas Gohr        $expect = 'foo:start';
151*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]);
152*98640fd3SAndreas Gohr        $this->assertEquals($expect, $actual, 'default existing');
153*98640fd3SAndreas Gohr    }
154*98640fd3SAndreas Gohr
155*98640fd3SAndreas Gohr    /**
156*98640fd3SAndreas Gohr     * @return array
157*98640fd3SAndreas Gohr     * @see testResolveRelatives
158*98640fd3SAndreas Gohr     */
159*98640fd3SAndreas Gohr    public function provideResolveRelatives()
160*98640fd3SAndreas Gohr    {
161*98640fd3SAndreas Gohr        return [
162*98640fd3SAndreas Gohr            ['foo', 'foo'],
163*98640fd3SAndreas Gohr            ['foo:bar', 'foo:bar'],
164*98640fd3SAndreas Gohr            ['foo:..:bar', 'bar'],
165*98640fd3SAndreas Gohr            ['foo:..:..:bar', 'bar'],
166*98640fd3SAndreas Gohr            ['foo:.:bar', 'foo:bar'],
167*98640fd3SAndreas Gohr            ['foo:.:..:.:bar', 'bar'],
168*98640fd3SAndreas Gohr            ['foo:.:.:.:bar', 'foo:bar'],
169*98640fd3SAndreas Gohr            ['foo::::bar', 'foo:bar'],
170*98640fd3SAndreas Gohr            ['foo::::bar:', 'foo:bar:'],
171*98640fd3SAndreas Gohr            ['foo:bar:', 'foo:bar:'],
172*98640fd3SAndreas Gohr        ];
173*98640fd3SAndreas Gohr    }
174*98640fd3SAndreas Gohr
175*98640fd3SAndreas Gohr    /**
176*98640fd3SAndreas Gohr     * @dataProvider provideResolveRelatives
177*98640fd3SAndreas Gohr     * @param string $input
178*98640fd3SAndreas Gohr     * @param string $expected
179*98640fd3SAndreas Gohr     */
180*98640fd3SAndreas Gohr    public function testResolveRelatives($input, $expected)
181*98640fd3SAndreas Gohr    {
182*98640fd3SAndreas Gohr        $resolver = new PageResolver('arbitrary');
183*98640fd3SAndreas Gohr
184*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveRelatives', [$input]);
185*98640fd3SAndreas Gohr        $this->assertEquals($expected, $actual);
186*98640fd3SAndreas Gohr    }
187*98640fd3SAndreas Gohr
188*98640fd3SAndreas Gohr    public function testAutoPlural()
189*98640fd3SAndreas Gohr    {
190*98640fd3SAndreas Gohr        $resolver = new PageResolver('arbitrary');
191*98640fd3SAndreas Gohr
192*98640fd3SAndreas Gohr        $singular = 'some:page';
193*98640fd3SAndreas Gohr        $plural = 'some:pages';
194*98640fd3SAndreas Gohr
195*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]);
196*98640fd3SAndreas Gohr        $this->assertEquals($singular, $actual); // no pages exist
197*98640fd3SAndreas Gohr
198*98640fd3SAndreas Gohr        saveWikiText($plural, 'plural', 'plural');
199*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]);
200*98640fd3SAndreas Gohr        $this->assertEquals($plural, $actual); // plural exists
201*98640fd3SAndreas Gohr
202*98640fd3SAndreas Gohr        saveWikiText($singular, 'singular', 'singular');
203*98640fd3SAndreas Gohr        $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]);
204*98640fd3SAndreas Gohr        $this->assertEquals($singular, $actual); // requested singular has preference
205*98640fd3SAndreas Gohr    }
206*98640fd3SAndreas Gohr}
207