You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

354 lines
15 KiB

  1. <?php
  2. use DOMWrap\Document;
  3. require_once DOKU_INC . 'inc/parser/xhtml.php';
  4. /**
  5. * @group plugin_indexmenu
  6. */
  7. class IndexmenuSyntaxTest extends DokuWikiTest
  8. {
  9. public function setup(): void
  10. {
  11. // global $conf;
  12. $this->pluginsEnabled[] = 'indexmenu';
  13. parent::setup();
  14. //$conf['plugin']['indexmenu']['headpage'] = '';
  15. //$conf['plugin']['indexmenu']['hide_headpage'] = false;
  16. //saveWikiText('titleonly:sub:test', "====== Title ====== \n content", 'created');
  17. //saveWikiText('test', "====== Title ====== \n content", 'created');
  18. //idx_addPage('titleonly:sub:test');
  19. //idx_addPage('test');
  20. }
  21. // public function __construct() {
  22. //// $this->exampleIndex = "{{indexmenu>:}}";
  23. //
  24. // parent::__construct();
  25. // }
  26. /**
  27. * Create from list of values the output array of handle()
  28. *
  29. * @param array $values
  30. * @return array aligned similar to output of handle()
  31. */
  32. private function createData($values)
  33. {
  34. [
  35. $ns, $theme, $identifier, $nocookie, $navbar, $noscroll, $maxjs, $notoc, $jsajax, $context, $nomenu,
  36. $sort, $msort, $rsort, $nsort, $level, $nons, $nopg, $subnss, $max, $maxAjax, $js, $skipns, $skipfile,
  37. $skipnscombined, $skipfilecombined, $hsort, $headpage, $hide_headpage, $jsVersion
  38. ] = $values;
  39. return [
  40. $ns,
  41. [
  42. 'theme' => $theme,
  43. 'identifier' => $identifier,
  44. 'nocookie' => $nocookie,
  45. 'navbar' => $navbar,
  46. 'noscroll' => $noscroll,
  47. 'maxJs' => $maxjs,
  48. 'notoc' => $notoc,
  49. 'jsAjax' => $jsajax,
  50. 'context' => $context,
  51. 'nomenu' => $nomenu,
  52. ],
  53. [
  54. 'sort' => $sort,
  55. 'msort' => $msort,
  56. 'rsort' => $rsort,
  57. 'nsort' => $nsort,
  58. 'hsort' => $hsort,
  59. ],
  60. [
  61. 'level' => $level,
  62. 'nons' => $nons,
  63. 'nopg' => $nopg,
  64. 'subnss' => $subnss,
  65. 'max' => $max,
  66. 'js' => $js,
  67. 'skipns' => $skipns,
  68. 'skipfile' => $skipfile,
  69. 'skipnscombined' => $skipnscombined,
  70. 'skipfilecombined' => $skipfilecombined,
  71. 'headpage' => $headpage,
  72. 'hide_headpage' => $hide_headpage,
  73. 'maxajax' => $maxAjax,
  74. 'navbar' => $navbar,
  75. 'theme' => $theme
  76. ],
  77. $jsVersion
  78. ];
  79. }
  80. /**
  81. * Data provider
  82. *
  83. * @return array[]
  84. */
  85. public static function someSyntaxes()
  86. {
  87. return [
  88. //root ns (empty is not recognized..)
  89. // [syntax, data]
  90. [
  91. "{{indexmenu>:}}",
  92. [
  93. '', 'default', 'random', false, false, false, 1, false, '', false, false,
  94. 0, false, false, false, -1, false, false, [], 0, 1, false, '', '', [''], [''], false,
  95. ":start:,:same:,:inside:", 1, 1
  96. ]
  97. ],
  98. //root ns, #levels=1, js renderer
  99. [
  100. "{{indexmenu>#1|js}}",
  101. [
  102. '', 'default', 'random', false, false, false, 1, false, '', false, false,
  103. 0, false, false, false, 1, false, false, [], 0, 1, true, '', '', [''], [''], false,
  104. ":start:,:same:,:inside:", 1, 1
  105. ]
  106. ],
  107. //root ns, #levels=2, all not js specific options (nocookie is from context)
  108. [
  109. "{{indexmenu>#2 test#6|navbar context tsort dsort msort hsort rsort nsort nons nopg}}",
  110. [
  111. '', 'default', 'random', true, true, false, 1, false, '&sort=t&msort=indexmenu_n&rsort=1&nsort=1&hsort=1&nopg=1', true, false,
  112. 't', 'indexmenu_n', true, true, 2, true, true, [['test', 6]], 0, 1, false, '', '', [''], [''], true,
  113. ":start:,:same:,:inside:", 1, 1
  114. ]
  115. ],
  116. //root ns, #levels=2, js renderer, all not js specific options
  117. [
  118. "{{indexmenu>#2 test#6|navbar js#bj_ubuntu.png context tsort dsort msort hsort rsort nsort nons nopg}}",
  119. [
  120. '', 'bj_ubuntu.png', 'random', true, true, false, 1, false, '&sort=t&msort=indexmenu_n&rsort=1&nsort=1&hsort=1&nopg=1', true, false,
  121. 't', 'indexmenu_n', true, true, 2, true, true, [['test', 6]], 0, 1, true, '', '', [''], [''], true,
  122. ":start:,:same:,:inside:", 1, 1
  123. ]
  124. ],
  125. //root ns, #levels=1, all options
  126. [
  127. "{{indexmenu>#1|navbar context nocookie noscroll notoc nomenu dsort msort#date:modified hsort rsort nsort nons nopg max#2#4 maxjs#3 id#54321}}",
  128. [
  129. '', 'default', 'random', true, true, true, 1, true, '&sort=d&msort=date modified&rsort=1&nsort=1&hsort=1&nopg=1', true, true,
  130. 'd', 'date modified', true, true, 1, true, true, [], 0, 1, false, '', '', [''], [''], true,
  131. ":start:,:same:,:inside:", 1, 1
  132. ]
  133. ],
  134. //root ns, #levels=1, js renderer, all options
  135. [
  136. "{{indexmenu>#1|js#bj_ubuntu.png navbar context nocookie noscroll notoc nomenu dsort msort#date:modified hsort rsort nsort nons nopg max#2#4 maxjs#3 id#54321}}",
  137. [
  138. '', 'bj_ubuntu.png', 54321, true, true, true, 3, true, '&sort=d&msort=date modified&rsort=1&nsort=1&hsort=1&nopg=1&max=4', true, true,
  139. 'd', 'date modified', true, true, 1, true, true, [], 2, 4, true, '', '', [''], [''], true,
  140. ":start:,:same:,:inside:", 1, 1
  141. ]
  142. ],
  143. //root ns, #levels=1, skipfile and ns
  144. [
  145. "{{indexmenu>#1 test|skipfile+/(^myusers:spaces$|privatens:userss)/ skipns=/(^myusers:spaces$|privatens:users)/ id#ns}}",
  146. [
  147. '', 'default', 'random', false, false, false, 1, false, '&skipns=%3D/%28%5Emyusers%3Aspaces%24%7Cprivatens%3Ausers%29/&skipfile=%2B/%28%5Emyusers%3Aspaces%24%7Cprivatens%3Auserss%29/', false, false,
  148. 0, false, false, false, 1, false, false, [['test', -1]], 0, 1, false, '=/(^myusers:spaces$|privatens:users)/',
  149. '+/(^myusers:spaces$|privatens:userss)/', ['/(^myusers:spaces$|privatens:users)/'], ['', '/(^myusers:spaces$|privatens:userss)/'], false,
  150. ":start:,:same:,:inside:", 1, 1
  151. ]
  152. ],
  153. //root ns, #levels=1, js renderer, skipfile and ns
  154. [
  155. "{{indexmenu>#1 test|js skipfile=/(^myusers:spaces$|privatens:userss)/ skipns+/(^myusers:spaces$|privatens:userssss)/ id#ns}}",
  156. [
  157. '', 'default', 0, false, false, false, 1, false, '&skipns=%2B/%28%5Emyusers%3Aspaces%24%7Cprivatens%3Auserssss%29/&skipfile=%3D/%28%5Emyusers%3Aspaces%24%7Cprivatens%3Auserss%29/', false, false,
  158. 0, false, false, false, 1, false, false, [['test', -1]], 0, 1, true, '+/(^myusers:spaces$|privatens:userssss)/',
  159. '=/(^myusers:spaces$|privatens:userss)/', ['', '/(^myusers:spaces$|privatens:userssss)/'], ['/(^myusers:spaces$|privatens:userss)/'], false,
  160. ":start:,:same:,:inside:", 1, 1
  161. ]
  162. ]
  163. ];
  164. }
  165. /**
  166. * Parse the syntax to options
  167. * expect: different combinations with or without js option, covers recognizing all syntax options
  168. *
  169. * @dataProvider someSyntaxes
  170. */
  171. public function testHandle($syntax, $changedData)
  172. {
  173. $plugin = new syntax_plugin_indexmenu_indexmenu();
  174. $null = new Doku_Handler();
  175. $result = $plugin->handle($syntax, 0, 40, $null);
  176. //copy unique generated number, which is about 23 characters
  177. $len_id = strlen($result[1]['identifier']);
  178. if (!is_numeric($changedData[2]) && ($len_id > 18 && $len_id <= 23)) {
  179. $changedData[2] = $result[1]['identifier'];
  180. }
  181. $data = $this->createData($changedData);
  182. $this->assertEquals($data, $result, 'Data array corrupted');
  183. }
  184. /**
  185. * Data provider
  186. *
  187. * @return array[]
  188. */
  189. public static function differentNSs()
  190. {
  191. $pageInRoot = 'page';
  192. $pageInLvl1 = 'ns:page';
  193. $pageInLvl2 = 'ns1:ns2:page';
  194. return [
  195. //indexmenu on page at root level
  196. ['{{indexmenu>|}}', '', [], $pageInRoot],
  197. ['{{indexmenu>#1}}', '', [], $pageInRoot],
  198. ['{{indexmenu>:}}', '', [], $pageInRoot],
  199. ['{{indexmenu>.}}', '', [], $pageInRoot],
  200. ['{{indexmenu>.:}}', '', [], $pageInRoot],
  201. ['{{indexmenu>..}}', '', [], $pageInRoot],
  202. ['{{indexmenu>..:}}', '', [], $pageInRoot],
  203. ['{{indexmenu>myns}}', 'myns', [], $pageInRoot],
  204. ['{{indexmenu>:myns}}', 'myns', [], $pageInRoot],
  205. ['{{indexmenu>.myns}}', 'myns', [], $pageInRoot],
  206. ['{{indexmenu>.:myns}}', 'myns', [], $pageInRoot],
  207. ['{{indexmenu>..myns}}', 'myns', [], $pageInRoot],
  208. ['{{indexmenu>..:myns}}', 'myns', [], $pageInRoot],
  209. //indexmenu on page in a namespace
  210. ['{{indexmenu>|}}', '', [], $pageInLvl1],
  211. ['{{indexmenu>#1}}', '', [], $pageInLvl1],
  212. ['{{indexmenu>:}}', '', [], $pageInLvl1],
  213. ['{{indexmenu>.}}', 'ns', [], $pageInLvl1],
  214. ['{{indexmenu>.:}}', 'ns', [], $pageInLvl1],
  215. ['{{indexmenu>..}}', '', [], $pageInLvl1],
  216. ['{{indexmenu>..:}}', '', [], $pageInLvl1],
  217. ['{{indexmenu>myns}}', 'myns', [], $pageInLvl1], //was ns:myns
  218. ['{{indexmenu>:myns}}', 'myns', [], $pageInLvl1],
  219. ['{{indexmenu>.myns}}', 'ns:myns', [], $pageInLvl1],
  220. ['{{indexmenu>.:myns}}', 'ns:myns', [], $pageInLvl1],
  221. ['{{indexmenu>..myns}}', 'myns', [], $pageInLvl1],
  222. ['{{indexmenu>..:myns}}', 'myns', [], $pageInLvl1],
  223. ['{{indexmenu>myns:myns}}', 'myns:myns', [], $pageInLvl2],
  224. //indexmenu on page in a namespace
  225. ['{{indexmenu>|}}', '', [], $pageInLvl2],
  226. ['{{indexmenu>#1}}', '', [], $pageInLvl2],
  227. ['{{indexmenu>:}}', '', [], $pageInLvl2],
  228. ['{{indexmenu>.}}', 'ns1:ns2', [], $pageInLvl2],
  229. ['{{indexmenu>.:}}', 'ns1:ns2', [], $pageInLvl2],
  230. ['{{indexmenu>..}}', '', [], $pageInLvl2], //strange indexmenu specific exception! TODO remove?
  231. ['{{indexmenu>..:}}', 'ns1', [], $pageInLvl2],
  232. ['{{indexmenu>myns}}', 'myns', [], $pageInLvl2], //was ns1:ns2:myns
  233. ['{{indexmenu>:myns}}', 'myns', [], $pageInLvl2],
  234. ['{{indexmenu>.myns}}', 'ns1:ns2:myns', [], $pageInLvl2],
  235. ['{{indexmenu>.:myns}}', 'ns1:ns2:myns', [], $pageInLvl2],
  236. ['{{indexmenu>..myns}}', 'ns1:myns', [], $pageInLvl2],
  237. ['{{indexmenu>..:myns}}', 'ns1:myns', [], $pageInLvl2],
  238. ['{{indexmenu>myns:myns}}', 'myns:myns', [], $pageInLvl2],
  239. ['{{indexmenu>..:..:myns}}', 'ns1:myns', [], 'ns1:ns2:ns3:page'],
  240. ['{{indexmenu>0}}', '0', [], 'ns1:page'], //was ns1:0
  241. //indexmenu on page at root level and subns
  242. ['{{indexmenu> #1|}}', '', [], $pageInLvl2], //no subns, spaces before are removed
  243. ['{{indexmenu>#1 #1}}', '', [['', 1]], $pageInLvl2],
  244. ['{{indexmenu>: :}}', '', [['', -1]], $pageInLvl2],
  245. ['{{indexmenu>. .}}', 'ns1:ns2', [['ns1:ns2', -1]], $pageInLvl2],
  246. ['{{indexmenu>.: .:}}', 'ns1:ns2', [['ns1:ns2', -1]], $pageInLvl2],
  247. ['{{indexmenu>.. ..}}', '', [['', -1]], $pageInLvl2],
  248. ['{{indexmenu>..: ..:}}', 'ns1', [['ns1', -1]], $pageInLvl2],
  249. ['{{indexmenu>myns myns}}', 'myns', [['myns', -1]], $pageInLvl2], //was ns1:ns2:myns
  250. ['{{indexmenu>:myns :myns}}', 'myns', [['myns', -1]], $pageInLvl2],
  251. ['{{indexmenu>.myns .myns}}', 'ns1:ns2:myns', [['ns1:ns2:myns', -1]], $pageInLvl2],
  252. ['{{indexmenu>.:myns .:myns}}', 'ns1:ns2:myns', [['ns1:ns2:myns', -1]], $pageInLvl2],
  253. ['{{indexmenu>..myns ..myns}}', 'ns1:myns', [['ns1:myns', -1]], $pageInLvl2],
  254. ['{{indexmenu>..:myns ..myns}}', 'ns1:myns', [['ns1:myns', -1]], $pageInLvl2],
  255. ['{{indexmenu>myns:myns myns:myns}}', 'myns:myns', [['myns:myns', -1]], $pageInLvl2],
  256. //indexmenu on page in a namespace
  257. ['{{indexmenu>|}}', '', [], $pageInLvl2],
  258. ['{{indexmenu>#1}}', '', [], $pageInLvl2],
  259. ['{{indexmenu>:}}', '', [], $pageInLvl2],
  260. ['{{indexmenu>.}}', 'ns1:ns2', [], $pageInLvl2],
  261. ['{{indexmenu>.:}}', 'ns1:ns2', [], $pageInLvl2],
  262. ['{{indexmenu>..}}', '', [], $pageInLvl2], //strange indexmenu specific exception! TODO remove?
  263. ['{{indexmenu>..:}}', 'ns1', [], $pageInLvl2],
  264. ['{{indexmenu>myns:}}', 'myns', [], $pageInLvl2], //was ns1:ns2:myns
  265. ['{{indexmenu>:myns:}}', 'myns', [], $pageInLvl2],
  266. ['{{indexmenu>.myns:}}', 'ns1:ns2:myns', [], $pageInLvl2],
  267. ['{{indexmenu>.:myns:}}', 'ns1:ns2:myns', [], $pageInLvl2],
  268. ['{{indexmenu>..myns:}}', 'ns1:myns', [], $pageInLvl2],
  269. ['{{indexmenu>..:myns:}}', 'ns1:myns', [], $pageInLvl2],
  270. ['{{indexmenu>myns:myns:}}', 'myns:myns', [], $pageInLvl2],
  271. ];
  272. }
  273. /**
  274. * Parse the syntax to options
  275. * expect: different combinations with or without js option, covers recognizing all syntax options
  276. *
  277. * @dataProvider differentNSs
  278. */
  279. public function testResolving($syntax, $expectedNs, $expectedSubNss, $pageWithIndexmenu)
  280. {
  281. global $ID;
  282. $ID = $pageWithIndexmenu;
  283. $plugin = new syntax_plugin_indexmenu_indexmenu();
  284. $null = new Doku_Handler();
  285. $result = $plugin->handle($syntax, 0, 40, $null);
  286. $this->assertEquals($expectedNs, $result[0], 'check resolved ns');
  287. $this->assertEquals($expectedSubNss, $result[3]['subnss'], 'check resolved subNSs');
  288. }
  289. /**
  290. * Rendering for nonexisting namespace
  291. * expect: no paragraph due to no message set
  292. * expect: one paragraph, since message set
  293. * expect: contains namespace which replaced {{ns}}
  294. * expect: message contained rendered italic syntax
  295. */
  296. public function testRenderEmptymsg()
  297. {
  298. global $conf;
  299. $noexistns = 'nonexisting:namespace';
  300. $emptyindexsyntax = "{{indexmenu>$noexistns}}";
  301. $xhtml = new Doku_Renderer_xhtml();
  302. $plugin = new syntax_plugin_indexmenu_indexmenu();
  303. $null = new Doku_Handler();
  304. $result = $plugin->handle($emptyindexsyntax, 0, 10, $null);
  305. //no empty message
  306. $plugin->render('xhtml', $xhtml, $result);
  307. $doc = (new Document())->html($xhtml->doc);
  308. $this->assertEquals(0, $doc->find('p')->count());
  309. // Fill in empty message
  310. $conf['plugin']['indexmenu']['empty_msg'] = 'This namespace is //empty//: {{ns}}';
  311. $plugin->render('xhtml', $xhtml, $result);
  312. $doc = (new Document())->html($xhtml->doc);
  313. $this->assertEquals(1, $doc->find('p')->count());
  314. // $this->assertEquals(1, $doc->find("p:contains($noexistns)")->count());
  315. $this->assertEquals(1, $doc->find("p em")->count());
  316. }
  317. }