1<?php
2
3/**
4 * Principle copied from _test/tests/lib/exe/ajax_requests.test.php and /lib/plugins/indexmenu/_test
5 *
6 * @group ajax
7 * @group plugin_linksuggest
8 * @group plugins
9 */
10class SuggestionAjaxRequestsTest extends DokuWikiTest
11{
12    public function setUp(): void
13    {
14        $this->pluginsEnabled[] = 'linksuggest';
15        parent::setUp(); // this enables the indexmenu plugin
16
17        //needed for 'tsort' to use First headings, sets title during search, otherwise as fallback page name used.
18//        global $conf;
19//        $conf['useheading'] = 'navigation';
20
21
22        saveWikiText('wiki:mpage', "======Cc======\nText", 'page with m in ns');
23        saveWikiText('wiki:wikisub:midpage', "======Dd======\nText", 'ns with w in ns');
24        saveWikiText('mm', "======Ee======\nText", 'page with m in root');
25
26        //ensures title is added to metadata of page
27        idx_addPage('mailinglist');
28        idx_addPage('wiki:syntax');
29        idx_addPage('wiki:dokuwiki');
30        idx_addPage('int:editandsavetest');
31        idx_addPage('wiki:mpage');
32        idx_addPage('wiki:wikisub:midpage');
33        idx_addPage('mm');
34
35        // pages on different levels
36        saveWikiText('ns1:ms2:apage', "======Bb======\nPage on level 2", 'Created page on level 2');
37        saveWikiText('ns1:ms1:apage', "======Ee======\nPage on level 2", 'Created page on level 2');
38        saveWikiText('ns1:ms1:lvl3:lvl4:apage', "======Cc======\nPage on levl 4", 'Page on level 4');
39        saveWikiText('ns1:ms1:lvl3:lpage2', "======Ccd======\nPage on levl 3", 'Page on level 3');
40        saveWikiText('ns1:ms1:lpage', "======Ccc======\nPage on levl 4", 'Page with l in ms1');
41        saveWikiText('ns1:ms1:start', "======Aa======\nPage on level 2", 'Startpage on level 2');
42        saveWikiText('ns1:ms0:mpage', "======Aa2======\nPage on level 2", 'Created page on level 2');
43        saveWikiText('ns1:apage', "======Dd======\nPage on level 1", 'Created page on level 1');
44        saveWikiText('ns1:ms1', "======Gg======\nPage on level 1", 'Created page on level 1');
45
46        //ensures title is added to metadata
47        idx_addPage('ns1:ms1:apage');
48        idx_addPage('ns1:ms1:lvl3:lvl4:apage');
49        idx_addPage('ns1:ms1:lvl3:lpage2');
50        idx_addPage('ns1:ms1:lpage');
51        idx_addPage('ns1:ms1:start');
52        idx_addPage('ns1:ms2:apage');
53        idx_addPage('ns1:ms0:bpage');
54        idx_addPage('ns1:apage');
55        idx_addPage('ns1:ms1');
56    }
57
58    /**
59     * DataProvider for the builtin Ajax calls
60     *
61     * @return array
62     */
63    public function linksuggestPageCalls()
64    {
65        return [
66            // Call, POST parameters, result function
67            [
68                'plugin_linksuggest',
69                ['id'=>'','ns'=>'','q'=>''],
70                'expectedResultAllinRoot'
71            ],[
72                'plugin_linksuggest',
73                ['id'=>'','ns'=>'','q'=>'m'],
74                'expectedResultPageinRoot'
75            ],[
76                'plugin_linksuggest',
77                ['id'=>'','ns'=>'','q'=>'w'],
78                'expectedResultNsinRoot'
79            ], [
80                'plugin_linksuggest',
81                ['id'=>'wiki:syntax','ns'=>'','q'=>''],
82                'expectedResultAllinNs'
83            ], [
84                'plugin_linksuggest',
85                ['id'=>'wiki:syntax','ns'=>'','q'=>':'],
86                'expectedResultOnlyrootinNs'
87            ],[
88                'plugin_linksuggest',
89                ['id'=>'wiki:syntax','ns'=>'','q'=>':m'],
90                'expectedResultOnlyrootminNs'
91            ],[
92                'plugin_linksuggest',
93                ['id'=>'wiki:syntax','ns'=>'','q'=>'m'],
94                'expectedResultPageinNs'
95            ],[
96                'plugin_linksuggest',
97                ['id'=>'wiki:syntax','ns'=>'','q'=>'w'],
98                'expectedResultrootNsinNs'
99            ],[
100                'plugin_linksuggest',
101                ['id'=>'ns1:ms1','ns'=>'','q'=>'.m'],
102                'expectedResultlocalNsinNs2'
103            ],[
104                'plugin_linksuggest',
105                ['id'=>'ns1:ms1','ns'=>'','q'=>'.:m'],
106                'expectedResultlocalNsinNs'
107            ],[
108                'plugin_linksuggest',
109                ['id'=>'ns1:ms1:apage','ns'=>'','q'=>'..m'],
110                'expectedResultlocalNsinParentNs2'
111            ],[
112                'plugin_linksuggest',
113                ['id'=>'ns1:ms1:apage','ns'=>'','q'=>'..:m'],
114                'expectedResultlocalNsinParentNs'
115            ],[//TODO also ~ ?
116                'plugin_linksuggest',
117                ['id'=>'ns1:ms1','ns'=>'','q'=>'~l'],
118                'expectedResultlocalNsinRelativetoPage2' //FIXME nothing found..
119            ],[
120                'plugin_linksuggest',
121                ['id'=>'ns1:ms1','ns'=>'','q'=>'~:l'],
122                'expectedResultlocalNsinRelativetoPage' //FIXME nothing found..
123            ],[
124                'plugin_linksuggest',
125                ['id'=>'','ns'=>'','q'=>'ns1:ms1:l'],
126                'expectedResultMorelvlsNsinRoot'
127            ],[
128                'plugin_linksuggest',
129                ['id'=>'ns1:ms1','ns'=>'','q'=>'.ms1:l'],
130                'expectedResultMorelvlsPageinNs'
131            ],[
132                'plugin_linksuggest',
133                ['id'=>'ns1:ms2:apage','ns'=>'','q'=>'..ms1:l'],
134                'expectedResultMorelvlslocalPginParentNs'
135            ],[
136                'plugin_linksuggest',
137                ['id'=>'ns1:ms2:apage','ns'=>'','q'=>'..:ms1:l'],
138                'expectedResultMorelvlslocalPginParentNs2'
139            ],[
140                'plugin_linksuggest',
141                ['id'=>'ns1:ms1','ns'=>'','q'=>'~lvl3:l'],
142                'expectedResultMorelvlslocalNsRelativetoPage'
143            ],[
144                'plugin_linksuggest',
145                ['id'=>'ns1:ms1','ns'=>'','q'=>'.ms1:lvl3:'],
146                'expectedResultMorelvlsinCurrentNsNopage'
147            ],[
148                'plugin_linksuggest',
149                ['id'=>'ns1:ms1:lvl3:lvl4:apage','ns'=>'','q'=>'ns1:ms2:..:ms1:lvl3:'],
150                'expectedResultRelativeParentinNsNotStart'
151            ]
152        ];
153    }
154
155    /**
156     * @dataProvider linksuggestPageCalls
157     * @param string $call
158     * @param array $post
159     * @param string $expectedResult
160     */
161    public function testPageSuggestions($call, $post, $expectedResult)
162    {
163        $request = new TestRequest();
164        $response = $request->post(['call' => $call] + $post, '/lib/exe/ajax.php');
165//        $this->assertNotEquals("AJAX call '$call' unknown!\n", $response->getContent());
166
167//var_export(json_decode($response->getContent()), true); // print as PHP array
168
169        $actualArray = json_decode($response->getContent(), true);
170
171        $this->assertEquals($this->$expectedResult(), $actualArray, "$expectedResult");
172    }
173
174
175
176    /**
177     * at root level '', query: '', return all at root lvl
178     */
179    public function expectedResultAllinRoot()
180    {
181        return [
182            'data' => [
183                0 => [
184                    'id' => 'int',
185                    'ns' => false,
186                    'type' => 'd',
187                    'title' => '',
188                    'rootns' => 1
189                ],
190                1 => [
191                    'id' => 'ns1',
192                    'ns' => false,
193                    'type' => 'd',
194                    'title' => '',
195                    'rootns' => 1
196                ],
197                2 => [
198                    'id' => 'wiki',
199                    'ns' => false,
200                    'type' => 'd',
201                    'title' => '',
202                    'rootns' => 1
203                ],
204                3 => [
205                    'id' => 'mailinglist',
206                    'ns' => ':',
207                    'type' => 'f',
208                    'title' => 'Mailing Lists',
209                    'rootns' => 1
210                ],
211                4 => [
212                    'id' => 'mm',
213                    'ns' => ':',
214                    'type' => 'f',
215                    'title' => 'Ee',
216                    'rootns' => 1
217                ]
218            ],
219            'link' => ''];
220    }
221    /**
222     * at root level '', query: m, return only start with m (pages) at root lvl
223     */
224    public function expectedResultPageinRoot()
225    {
226        return [
227            'data' => [
228                0 => [
229                    'id' => 'mailinglist',
230                    'ns' => ':',
231                    'type' => 'f',
232                    'title' => 'Mailing Lists',
233                    'rootns' => 1
234                ],
235                1 => [
236                    'id' => 'mm',
237                    'ns' => ':',
238                    'type' => 'f',
239                    'title' => 'Ee',
240                    'rootns' => 1
241                ]
242            ],
243            'link' => ''];
244    }
245    /**
246     * at root level '', query: w, return only start with w (namespace) at root lvl
247     */
248    public function expectedResultNsinRoot()
249    {
250        return [
251            'data' => [
252                0 => [
253                    'id' => 'wiki',
254                    'ns' => false,
255                    'type' => 'd',
256                    'title' => '',
257                    'rootns' => 1
258                ]
259            ],
260            'link' => ''];
261    }
262
263    /**
264     * at ns level 'wiki:syntax', query: '', results from two level: ns & root
265     */
266    public function expectedResultAllinNs()
267    {
268        return [
269            'data' => [
270                0 => [
271                    'id' => 'dokuwiki',
272                    'ns' => false,//relative
273                    'type' => 'f',
274                    'title' => 'DokuWiki',
275                    'rootns' => 0
276                ],
277                1 => [
278                    'id' => 'mpage',
279                    'ns' => false,//relative
280                    'type' => 'f',
281                    'title' => 'Cc',
282                    'rootns' => 0
283                ],
284                2 => [
285                    'id' => 'syntax',
286                    'ns' => false,//relative
287                    'type' => 'f',
288                    'title' => 'Formatting Syntax',
289                    'rootns' => 0
290                ],
291                3 => [
292                    'id' => 'int',
293                    'ns' => false,
294                    'type' => 'd',
295                    'title' => '',
296                    'rootns' => 1
297                ],
298                4 => [
299                    'id' => 'ns1',
300                    'ns' => false,
301                    'type' => 'd',
302                    'title' => '',
303                    'rootns' => 1
304                ],
305                5 => [
306                    'id' => 'wiki',
307                    'ns' => false,
308                    'type' => 'd',
309                    'title' => '',
310                    'rootns' => 1
311                ],
312                6 => [
313                    'id' => 'mailinglist',
314                    'ns' => ':',
315                    'type' => 'f',
316                    'title' => 'Mailing Lists',
317                    'rootns' => 1
318                ],
319                7 => [
320                    'id' => 'mm',
321                    'ns' => ':',
322                    'type' => 'f',
323                    'title' => 'Ee',
324                    'rootns' => 1
325                ]
326            ],
327            'link' => ''];
328    }
329    /**
330     * at ns level 'wiki:syntax', query: ':' , results from only root
331     */
332    public function expectedResultOnlyrootinNs()
333    {
334        return [
335            'data' => [
336                0 => [
337                    'id' => 'int',
338                    'ns' => ':',
339                    'type' => 'd',
340                    'title' => '',
341                    'rootns' => 1
342                ],
343                1 => [
344                    'id' => 'ns1',
345                    'ns' => ':',
346                    'type' => 'd',
347                    'title' => '',
348                    'rootns' => 1
349                ],
350                2 => [
351                    'id' => 'wiki',
352                    'ns' => ':',
353                    'type' => 'd',
354                    'title' => '',
355                    'rootns' => 1
356                ],
357                3 => [
358                    'id' => 'mailinglist',
359                    'ns' => ':',
360                    'type' => 'f',
361                    'title' => 'Mailing Lists',
362                    'rootns' => 1
363                ],
364                4 => [
365                    'id' => 'mm',
366                    'ns' => ':',
367                    'type' => 'f',
368                    'title' => 'Ee',
369                    'rootns' => 1
370                ]
371            ],
372            'link' => ''];
373    }
374    /**
375     * at ns level 'wiki:syntax', query: ':m' , results from root which start with m
376     */
377    public function expectedResultOnlyrootminNs()
378    {
379        return [
380            'data' => [
381                0 => [
382                    'id' => 'mailinglist',
383                    'ns' => ':',
384                    'type' => 'f',
385                    'title' => 'Mailing Lists',
386                    'rootns' => 1
387                ],
388                1 => [
389                    'id' => 'mm',
390                    'ns' => ':',
391                    'type' => 'f',
392                    'title' => 'Ee',
393                    'rootns' => 1
394                ]
395            ],
396            'link' => ''];
397    }
398    /**
399     * at ns level 'wiki:syntax', query 'm', results from two level: ns & root starting with m
400     */
401    public function expectedResultPageinNs()
402    {
403        return [
404            'data' => [
405                0 => [
406                    'id' => 'mpage',
407                    'ns' => false,
408                    'type' => 'f',
409                    'title' => 'Cc',
410                    'rootns' => 0
411                ],
412                1=> [
413                    'id' => 'mailinglist',
414                    'ns' => ':',
415                    'type' => 'f',
416                    'title' => 'Mailing Lists',
417                    'rootns' => 1
418                ],
419                2 => [
420                    'id' => 'mm',
421                    'ns' => ':',
422                    'type' => 'f',
423                    'title' => 'Ee',
424                    'rootns' => 1
425                ]
426            ],
427            'link' => ''];
428    }
429    /**
430     * at ns level 'wiki:syntax', query 'w', results from only root level (for wikisub, .wikisub should be used)
431     */
432    public function expectedResultrootNsinNs()
433    {
434        return [
435            'data' => [
436                0 => [
437                    'id' => 'wiki',
438                    'ns' => false,
439                    'type' => 'd',
440                    'title' => '',
441                    'rootns' => 1
442                ]
443            ],
444            'link' => ''];
445    }
446    /**
447     * at ns level 'ns1:ms1', query '.m', results from only ns1: starting with m
448     */
449    public function expectedResultlocalNsinNs2()
450    {
451        return $this->expectedResultlocalNsinNs(false);
452    }
453    /**
454     * at ns level 'ns1:ms1', query '.:m', results from only ns1: starting with m
455     */
456    public function expectedResultlocalNsinNs($withSemicolon = true)
457    {
458        return [
459            'data' => [
460                0 => [
461                    'id' => 'ms0',
462                    'ns' => '.' . ($withSemicolon ? ':' : ''),
463                    'type' => 'd',
464                    'title' => '',
465                    'rootns' => 0
466                ],
467                1 => [
468                    'id' => 'ms1',
469                    'ns' => '.' . ($withSemicolon ? ':' : ''),
470                    'type' => 'd',
471                    'title' => '',
472                    'rootns' => 0
473                ],
474                2 => [
475                    'id' => 'ms2',
476                    'ns' => '.' . ($withSemicolon ? ':' : ''),
477                    'type' => 'd',
478                    'title' => '',
479                    'rootns' => 0
480                ],
481                3 => [
482                    'id' => 'ms1',
483                    'ns' => '.' . ($withSemicolon ? ':' : ''),
484                    'type' => 'f',
485                    'title' => 'Gg',
486                    'rootns' => 0
487                ]
488            ],
489            'link' => ''];
490    }
491    /**
492     * at ns level 'ns1:ms1:apage', query '..m', from only parent ns 'ns1:' starting with m
493     */
494    public function expectedResultlocalNsinParentNs2()
495    {
496        return $this->expectedResultlocalNsinParentNs(false);
497    }
498    /**
499     * at ns level 'ns1:ms1:apage', query '..:m', from only parent ns 'ns1:' starting with m
500     */
501    public function expectedResultlocalNsinParentNs($withSemicolon = true)
502    {
503        return [
504            'data' => [
505                0 => [
506                    'id' => 'ms0',
507                    'ns' => '..' . ($withSemicolon ? ':' : ''),
508                    'type' => 'd',
509                    'title' => '',
510                    'rootns' => 0
511                ],
512                1 => [
513                    'id' => 'ms1',
514                    'ns' => '..' . ($withSemicolon ? ':' : ''),
515                    'type' => 'd',
516                    'title' => '',
517                    'rootns' => 0
518                ],
519                2 => [
520                    'id' => 'ms2',
521                    'ns' => '..' . ($withSemicolon ? ':' : ''),
522                    'type' => 'd',
523                    'title' => '',
524                    'rootns' => 0
525                ],
526                3 => [
527                    'id' => 'ms1',
528                    'ns' => '..' . ($withSemicolon ? ':' : ''),
529                    'type' => 'f',
530                    'title' => 'Gg',
531                    'rootns' => 0
532                ]
533            ],
534            'link' => ''];
535    }
536    /**
537     * from page 'ns1:ms1', query '~l', result from namespace equal to current pageid 'ns1:ms1:' starting with l
538     */
539    public function expectedResultlocalNsinRelativetoPage2()
540    {
541        return $this->expectedResultlocalNsinRelativetoPage(false);
542    }
543    /**
544     * from page 'ns1:ms1', query '~:l', result from namespace equal to current pageid 'ns1:ms1:' starting with l
545     */
546    public function expectedResultlocalNsinRelativetoPage($withSemicolon = true)
547    {
548        return [
549            'data' => [
550                0 => [
551                    'id' => 'lvl3',
552                    'ns' => '~' . ($withSemicolon ? ':' : ''),
553                    'type' => 'd',
554                    'title' => '',
555                    'rootns' => 0
556                ],
557                1 => [
558                    'id' => 'lpage',
559                    'ns' => '~' . ($withSemicolon ? ':' : ''),
560                    'type' => 'f',
561                    'title' => 'Ccc',
562                    'rootns' => 0
563                ]
564            ],
565            'link' => ''];
566    }
567    /**
568     * at root level '', query: 'ns1:ms1:l', return specific hit in root
569     */
570    public function expectedResultMorelvlsNsinRoot()
571    {
572        return [
573            'data' => [
574                0 => [
575                    'id' => 'lvl3',
576                    'ns' => 'ns1:ms1:',
577                    'type' => 'd',
578                    'title' => '',
579                    'rootns' => 0
580                ],
581                1 => [
582                    'id' => 'lpage',
583                    'ns' => 'ns1:ms1:',
584                    'type' => 'f',
585                    'title' => 'Ccc',
586                    'rootns' => 0
587                ]
588            ],
589            'link' => ''];
590    }
591    /**
592     * at 'ns1:ms1', query: '.ms1:l' , return specific hit in ns 'ns1:ms1:' starting with l
593     */
594    public function expectedResultMorelvlsPageinNs()
595    {
596        return [
597            'data' => [
598                0 => [
599                    'id' => 'lvl3',
600                    'ns' => '.ms1:',
601                    'type' => 'd',
602                    'title' => '',
603                    'rootns' => 0
604                ],
605                1 => [
606                    'id' => 'lpage',
607                    'ns' => '.ms1:',
608                    'type' => 'f',
609                    'title' => 'Ccc',
610                    'rootns' => 0
611                ]
612            ],
613            'link' => ''];
614    }
615    /**
616     * at 'ns1:ms2:apage', query: '..ms1:l' , return specific hit in 'ns1:ms1:' starting with l
617     */
618    public function expectedResultMorelvlslocalPginParentNs()
619    {
620        return [
621            'data' => [
622                0 => [
623                    'id' => 'lvl3',
624                    'ns' => '..ms1:',
625                    'type' => 'd',
626                    'title' => '',
627                    'rootns' => 0
628                ],
629                1 => [
630                    'id' => 'lpage',
631                    'ns' => '..ms1:',
632                    'type' => 'f',
633                    'title' => 'Ccc',
634                    'rootns' => 0
635                ]
636            ],
637            'link' => ''];
638    }
639    /**
640     * at 'ns1:ms2:apage', query: '..:ms1:l' , return specific hit in 'ns1:ms1:' starting with l
641     */
642    public function expectedResultMorelvlslocalPginParentNs2()
643    {
644        return [
645            'data' => [
646                0 => [
647                    'id' => 'lvl3',
648                    'ns' => '..:ms1:',
649                    'type' => 'd',
650                    'title' => '',
651                    'rootns' => 0
652                ],
653                1 => [
654                    'id' => 'lpage',
655                    'ns' => '..:ms1:',
656                    'type' => 'f',
657                    'title' => 'Ccc',
658                    'rootns' => 0
659                ]
660            ],
661            'link' => ''];
662    }
663    /**
664     * at 'ns1:ms1', query: ~lvl3:l, return specific hit 'ns1:ms1:lvl3:' starting with l
665     */
666    public function expectedResultMorelvlslocalNsRelativetoPage()
667    {
668        return [
669            'data' => [
670                0 => [
671                    'id' => 'lvl4',
672                    'ns' => '~lvl3:',
673                    'type' => 'd',
674                    'title' => '',
675                    'rootns' => 0
676                ],
677                1 => [
678                    'id' => 'lpage2',
679                    'ns' => '~lvl3:',
680                    'type' => 'f',
681                    'title' => 'Ccd',
682                    'rootns' => 0
683                ]
684            ],
685            'link' => ''];
686    }
687    /**
688     * in 'ns1:ms1', query: '.ms1:lvl3:', return all in 'ns1:ms1:lvl3:' namespace
689     */
690    public function expectedResultMorelvlsinCurrentNsNopage()
691    {
692        return [
693            'data' => [
694                0 => [
695                    'id' => 'lvl4',
696                    'ns' => '.ms1:lvl3:',
697                    'type' => 'd',
698                    'title' => '',
699                    'rootns' => 0
700                ],
701                1 => [
702                    'id' => 'lpage2',
703                    'ns' => '.ms1:lvl3:',
704                    'type' => 'f',
705                    'title' => 'Ccd',
706                    'rootns' => 0
707                ]
708            ],
709            'link' => ''];
710    }
711    /**
712     * in 'ns1:ms1:lvl3:lvl4:apage', query: ns1:ms2:..:ms1:lvl3:', return all in 'ns1:ms1:lvl3:' namespace
713     */
714    public function expectedResultRelativeParentinNsNotStart()
715    {
716        return [
717            'data' => [
718                0 => [
719                    'id' => 'lvl4',
720                    'ns' => 'ns1:ms2:..:ms1:lvl3:',
721                    'type' => 'd',
722                    'title' => '',
723                    'rootns' => 0
724                ],
725                1 => [
726                    'id' => 'lpage2',
727                    'ns' => 'ns1:ms2:..:ms1:lvl3:',
728                    'type' => 'f',
729                    'title' => 'Ccd',
730                    'rootns' => 0
731                ]
732            ],
733            'link' => ''];
734    }
735}
736