1<?php 2 3/** 4 * @group plugin_bpmnio 5 * @group plugins 6 */ 7class syntax_plugin_bpmnio_test extends DokuWikiTest 8{ 9 protected $pluginsEnabled = array('bpmnio'); 10 11 public function test_syntax_bpmn() 12 { 13 $info = array(); 14 $expected = <<<OUT 15 <div class="plugin-bpmnio" id="__bpmn_js_1"><div class="bpmn_js_data"> 16 ClhNTC4uLgo= 17 </div> 18 <div class="bpmn_js_links"> 19 W10= 20 </div><div class="bpmn_js_canvas sectionedit1"> 21 <div class="bpmn_js_container"></div> 22 </div><!-- EDIT{"target":"plugin_bpmnio_bpmn","secid":1,"range":"21-29"} --></div> 23 OUT; 24 25 $input = <<<IN 26 <bpmnio type="bpmn"> 27 XML... 28 </bpmnio> 29 IN; 30 31 $instructions = p_get_instructions($input); 32 $xhtml = p_render('xhtml', $instructions, $info); 33 34 $this->assertEquals($expected, $xhtml); 35 } 36 37 public function test_syntax_dmn() 38 { 39 $info = array(); 40 $expected = <<<OUT 41 <div class="plugin-bpmnio" id="__dmn_js_1"><div class="dmn_js_data"> 42 ClhNTC4uLgo= 43 </div> 44 <div class="dmn_js_links"> 45 W10= 46 </div><div class="dmn_js_canvas sectionedit1"> 47 <div class="dmn_js_container"></div> 48 </div><!-- EDIT{"target":"plugin_bpmnio_dmn","secid":1,"range":"20-28"} --></div> 49 OUT; 50 51 $input = <<<IN 52 <bpmnio type="dmn"> 53 XML... 54 </bpmnio> 55 IN; 56 57 $instructions = p_get_instructions($input); 58 $xhtml = p_render('xhtml', $instructions, $info); 59 60 $this->assertEquals($expected, $xhtml); 61 } 62 63 /** 64 * Test that type defaults to bpmn when not specified 65 */ 66 public function test_syntax_default_type() 67 { 68 $info = array(); 69 70 $input = <<<IN 71 <bpmnio> 72 XML... 73 </bpmnio> 74 IN; 75 76 $instructions = p_get_instructions($input); 77 $xhtml = p_render('xhtml', $instructions, $info); 78 79 $this->assertStringContainsString('bpmn_js_data', $xhtml); 80 $this->assertStringContainsString('bpmn_js_canvas', $xhtml); 81 $this->assertStringContainsString('bpmn_js_container', $xhtml); 82 } 83 84 /** 85 * Test empty content between tags 86 */ 87 public function test_syntax_empty_content() 88 { 89 $info = array(); 90 91 $input = <<<IN 92 <bpmnio type="bpmn"> 93 </bpmnio> 94 IN; 95 96 $instructions = p_get_instructions($input); 97 $xhtml = p_render('xhtml', $instructions, $info); 98 99 // Should still produce the structure, with base64 of whitespace/empty 100 $this->assertStringContainsString('plugin-bpmnio', $xhtml); 101 $this->assertStringContainsString('bpmn_js_data', $xhtml); 102 } 103 104 /** 105 * Test that multiline XML content is properly base64-encoded 106 */ 107 public function test_syntax_multiline_content() 108 { 109 $info = array(); 110 111 $input = <<<IN 112 <bpmnio type="bpmn"> 113 <?xml version="1.0"?> 114 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> 115 </definitions> 116 </bpmnio> 117 IN; 118 119 $instructions = p_get_instructions($input); 120 $xhtml = p_render('xhtml', $instructions, $info); 121 122 $this->assertStringContainsString('bpmn_js_data', $xhtml); 123 // Verify the data section contains valid base64 124 preg_match('/<div class="bpmn_js_data">\s*(.*?)\s*<\/div>/s', $xhtml, $matches); 125 $this->assertNotEmpty($matches[1]); 126 $decoded = base64_decode(trim($matches[1]), true); 127 $this->assertNotFalse($decoded, 'Content should be valid base64'); 128 $this->assertStringContainsString('definitions', $decoded); 129 } 130 131 /** 132 * Test that the plugin produces section edit markers for inline content 133 */ 134 public function test_syntax_section_edit_bpmn() 135 { 136 $info = array(); 137 138 $input = <<<IN 139 <bpmnio type="bpmn"> 140 Content 141 </bpmnio> 142 IN; 143 144 $instructions = p_get_instructions($input); 145 $xhtml = p_render('xhtml', $instructions, $info); 146 147 $this->assertStringContainsString('sectionedit', $xhtml); 148 $this->assertStringContainsString('plugin_bpmnio_bpmn', $xhtml); 149 } 150 151 /** 152 * Test that the plugin produces section edit markers for DMN inline content 153 */ 154 public function test_syntax_section_edit_dmn() 155 { 156 $info = array(); 157 158 $input = <<<IN 159 <bpmnio type="dmn"> 160 Content 161 </bpmnio> 162 IN; 163 164 $instructions = p_get_instructions($input); 165 $xhtml = p_render('xhtml', $instructions, $info); 166 167 $this->assertStringContainsString('sectionedit', $xhtml); 168 $this->assertStringContainsString('plugin_bpmnio_dmn', $xhtml); 169 } 170 171 /** 172 * Test that unrecognized text outside <bpmnio> is not affected 173 */ 174 public function test_syntax_no_interference() 175 { 176 $info = array(); 177 178 $input = <<<IN 179 Hello World 180 <bpmnio type="bpmn"> 181 XML... 182 </bpmnio> 183 Goodbye World 184 IN; 185 186 $instructions = p_get_instructions($input); 187 $xhtml = p_render('xhtml', $instructions, $info); 188 189 $this->assertStringContainsString('Hello World', $xhtml); 190 $this->assertStringContainsString('Goodbye World', $xhtml); 191 $this->assertStringContainsString('plugin-bpmnio', $xhtml); 192 } 193 194 public function test_syntax_zoom_attribute() 195 { 196 $info = array(); 197 198 $input = <<<IN 199 <bpmnio type="bpmn" zoom="0.5"> 200 XML... 201 </bpmnio> 202 IN; 203 204 $instructions = p_get_instructions($input); 205 $xhtml = p_render('xhtml', $instructions, $info); 206 207 $this->assertStringContainsString('data-zoom="0.5"', $xhtml); 208 } 209 210 public function test_syntax_ignores_invalid_zoom_attribute() 211 { 212 $info = array(); 213 214 $input = <<<IN 215 <bpmnio type="bpmn" zoom="0"> 216 XML... 217 </bpmnio> 218 IN; 219 220 $instructions = p_get_instructions($input); 221 $xhtml = p_render('xhtml', $instructions, $info); 222 223 $this->assertStringNotContainsString('data-zoom=', $xhtml); 224 } 225 226 public function test_syntax_builds_link_payload_for_named_elements() 227 { 228 $info = array(); 229 io_mkdir_p(dirname(wikiFN('docs:start'))); 230 io_saveFile(wikiFN('docs:start'), 'Read docs'); 231 232 $input = <<<IN 233 <bpmnio type="bpmn"> 234 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> 235 <process id="Process_1"> 236 <task id="Task_1" name="[[:docs:start|Read docs]]" /> 237 </process> 238 </definitions> 239 </bpmnio> 240 IN; 241 242 $instructions = p_get_instructions($input); 243 $xhtml = p_render('xhtml', $instructions, $info); 244 245 preg_match('/<div class="bpmn_js_data">\s*(.*?)\s*<\/div>/s', $xhtml, $xmlMatch); 246 $this->assertNotEmpty($xmlMatch[1]); 247 $decodedXml = base64_decode(trim($xmlMatch[1]), true); 248 $this->assertNotFalse($decodedXml); 249 $this->assertStringContainsString('name="Read docs"', $decodedXml); 250 $this->assertStringNotContainsString('[[', $decodedXml); 251 252 preg_match('/<div class="bpmn_js_links">\s*(.*?)\s*<\/div>/s', $xhtml, $linkMatch); 253 $this->assertNotEmpty($linkMatch[1]); 254 $decodedLinks = base64_decode(trim($linkMatch[1]), true); 255 $this->assertNotFalse($decodedLinks); 256 $links = json_decode($decodedLinks, true); 257 258 $this->assertIsArray($links); 259 $this->assertArrayHasKey('Task_1', $links); 260 $this->assertEquals('/doku.php?id=docs%3Astart', $links['Task_1']['href']); 261 $this->assertEquals('docs:start', $links['Task_1']['target']); 262 } 263 264 public function test_syntax_keeps_unlinked_names_unchanged() 265 { 266 $info = array(); 267 268 $input = <<<IN 269 <bpmnio type="dmn"> 270 <?xml version="1.0" encoding="UTF-8"?> 271 <definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/" id="Definitions_1"> 272 <decision id="Decision_1" name="Approve Order" /> 273 </definitions> 274 </bpmnio> 275 IN; 276 277 $instructions = p_get_instructions($input); 278 $xhtml = p_render('xhtml', $instructions, $info); 279 280 preg_match('/<div class="dmn_js_data">\s*(.*?)\s*<\/div>/s', $xhtml, $xmlMatch); 281 $decodedXml = base64_decode(trim($xmlMatch[1]), true); 282 $this->assertNotFalse($decodedXml); 283 $this->assertStringContainsString('Approve Order', $decodedXml); 284 285 preg_match('/<div class="dmn_js_links">\s*(.*?)\s*<\/div>/s', $xhtml, $linkMatch); 286 $decodedLinks = base64_decode(trim($linkMatch[1]), true); 287 $this->assertSame('[]', $decodedLinks); 288 } 289 290 /** 291 * Test the handle method directly for ENTER state 292 */ 293 public function test_handle_enter_state() 294 { 295 $plugin = plugin_load('syntax', 'bpmnio_bpmnio'); 296 $this->assertNotNull($plugin, 'Plugin should be loadable'); 297 298 $handler = new Doku_Handler(); 299 $result = $plugin->handle('<bpmnio type="bpmn">', DOKU_LEXER_ENTER, 0, $handler); 300 301 $this->assertEquals(DOKU_LEXER_ENTER, $result[0]); 302 $this->assertEquals('bpmn', $result[1]); 303 } 304 305 /** 306 * Test the handle method directly for EXIT state 307 */ 308 public function test_handle_exit_state() 309 { 310 $plugin = plugin_load('syntax', 'bpmnio_bpmnio'); 311 $handler = new Doku_Handler(); 312 $result = $plugin->handle('</bpmnio>', DOKU_LEXER_EXIT, 0, $handler); 313 314 $this->assertEquals(DOKU_LEXER_EXIT, $result[0]); 315 } 316 317 /** 318 * Test that the plugin is correctly registered 319 */ 320 public function test_plugin_registration() 321 { 322 $plugin = plugin_load('syntax', 'bpmnio_bpmnio'); 323 $this->assertNotNull($plugin, 'Plugin should be loadable'); 324 $this->assertEquals('block', $plugin->getPType()); 325 $this->assertEquals('protected', $plugin->getType()); 326 $this->assertEquals(0, $plugin->getSort()); 327 } 328} 329