1<?php 2 3namespace dokuwiki\plugin\struct\test; 4 5use dokuwiki\plugin\struct\meta\Column; 6use dokuwiki\plugin\struct\meta\NestedResult; 7use dokuwiki\plugin\struct\meta\Value; 8use dokuwiki\plugin\struct\types\Text; 9 10/** 11 * Tests for the NestedResult class 12 * 13 * @group plugin_struct 14 * @group plugins 15 * 16 */ 17class NestedResultTest extends StructTest 18{ 19 protected $simpleItems = [ 20 ['car', 'audi', 'a80'], 21 ['car', 'audi', 'a4'], 22 ['car', 'audi', 'quattro'], 23 ['car', 'bmw', 'i3'], 24 ['car', 'bmw', 'mini'], 25 ['car', 'bmw', 'z1'], 26 ['laptop', 'apple', 'pro 16'], 27 ['laptop', 'apple', 'air'], 28 ['laptop', 'apple', 'm1'], 29 ['laptop', 'dell', 'xps'], 30 ['laptop', 'dell', 'inspiron'], 31 ['laptop', 'dell', 'latitude'], 32 ]; 33 34 protected $multiItems = [ 35 [['green', 'yellow'], 'car', 'audi', 'a80'], 36 [['yellow', 'blue'], 'car', 'audi', 'a4'], 37 [['black', 'green'], 'car', 'audi', 'quattro'], 38 [['red', 'black'], 'car', 'bmw', 'i3'], 39 [['blue', 'gray'], 'car', 'bmw', 'mini'], 40 [['red', 'black'], 'car', 'bmw', 'z1'], 41 [['green', 'blue'], 'laptop', 'apple', 'pro 16'], 42 [['red', 'blue'], 'laptop', 'apple', 'air'], 43 [['black', 'red'], 'laptop', 'apple', 'm1'], 44 [['gray', 'green'], 'laptop', 'dell', 'xps'], 45 [['blue', 'yellow'], 'laptop', 'dell', 'inspiron'], 46 [['gray', 'yellow'], 'laptop', 'dell', 'latitude'], 47 ]; 48 49 protected $multiHoleItems = [ 50 [['green', 'yellow'], 'car', 'audi', 'a80'], 51 [[], 'car', 'audi', 'a4'], 52 [['black', 'green'], '', 'audi', 'quattro'], 53 [['red', 'black'], 'car', 'bmw', 'i3'], 54 [['blue', 'gray'], 'car', 'bmw', 'mini'], 55 [['red', 'black'], 'car', 'bmw', 'z1'], 56 [['green', 'blue'], 'laptop', 'apple', 'pro 16'], 57 [['red', 'blue'], 'laptop', 'apple', 'air'], 58 [['black', 'red'], 'laptop', 'apple', 'm1'], 59 [[], 'laptop', 'dell', 'xps'], 60 [['blue', 'yellow'], '', 'dell', 'inspiron'], 61 [['gray', 'yellow'], 'laptop', 'dell', 'latitude'], 62 ]; 63 64 protected $multiMultiItems = [ 65 [['metal', 'wood'], ['green', 'yellow'], 'car', 'audi', 'a80'], 66 [['metal', 'wood', 'plastic'], ['yellow', 'blue'], 'car', 'audi', 'a4'], 67 [['plastic', 'metal'], ['red', 'blue'], 'laptop', 'apple', 'pro 16'], 68 [['metal', 'plastic'], ['black', 'red'], 'laptop', 'apple', 'air'], 69 ]; 70 71 72 /** 73 * Create a result set from a given flat array 74 * @param array $rows 75 * @return array 76 */ 77 protected function makeResult($rows) 78 { 79 $result = []; 80 81 foreach ($rows as $row) { 82 $resultRow = []; 83 foreach ($row as $cell) { 84 $resultRow[] = new Value( 85 new Column( 86 10, 87 new Text(null, '', is_array($cell)), 88 0, 89 true, 90 'test' 91 ), 92 $cell 93 ); 94 } 95 $result[] = $resultRow; 96 } 97 98 return $result; 99 } 100 101 /** 102 * Don't nest at all 103 */ 104 public function testSimpleZeroLevel() 105 { 106 $result = $this->makeResult($this->simpleItems); 107 $nestedResult = new NestedResult($result); 108 $root = $nestedResult->getRoot(0); 109 110 $this->assertCount(0, $root->getChildren(), 'no children expected'); 111 $this->assertCount(12, $root->getResultRows(), '12 result rows expected'); 112 } 113 114 115 /** 116 * Nest by the first level, no multi values 117 */ 118 public function testSimpleOneLevel() 119 { 120 $result = $this->makeResult($this->simpleItems); 121 $nestedResult = new NestedResult($result); 122 $root = $nestedResult->getRoot(1); 123 $tree = $root->getChildren(); 124 125 $this->assertCount(2, $tree, '2 root nodes expected'); 126 $this->assertEquals('car', $tree[0]->getValueObject()->getValue()); 127 $this->assertEquals('laptop', $tree[1]->getValueObject()->getValue()); 128 129 $this->assertCount(0, $tree[0]->getChildren(), 'no children expected'); 130 $this->assertCount(0, $tree[1]->getChildren(), 'no children expected'); 131 132 $this->assertCount(6, $tree[0]->getResultRows(), 'result rows'); 133 $this->assertCount(6, $tree[1]->getResultRows(), 'result rows'); 134 135 $this->assertEquals('a80', $tree[0]->getResultRows()[0][1]->getValue(), 'Audi 80 expected'); 136 $this->assertEquals('pro 16', $tree[1]->getResultRows()[0][1]->getValue(), 'Mac Pro 16 expected'); 137 } 138 139 140 /** 141 * Nest by two levels, no multi values 142 */ 143 public function testSimpleTwoLevels() 144 { 145 $result = $this->makeResult($this->simpleItems); 146 $nestedResult = new NestedResult($result); 147 $root = $nestedResult->getRoot(2); 148 $tree = $root->getChildren(); 149 150 $this->assertCount(2, $tree, '2 root nodes expected'); 151 $this->assertEquals('car', $tree[0]->getValueObject()->getValue()); 152 $this->assertEquals('laptop', $tree[1]->getValueObject()->getValue()); 153 154 $this->assertCount(2, $tree[0]->getChildren(), '2 second level nodes expected'); 155 $this->assertCount(2, $tree[1]->getChildren(), '2 second level nodes expected'); 156 157 $this->assertCount(3, $tree[0]->getChildren()[0]->getResultRows(), 'result rows'); 158 $this->assertCount(3, $tree[0]->getChildren()[1]->getResultRows(), 'result rows'); 159 $this->assertCount(3, $tree[1]->getChildren()[0]->getResultRows(), 'result rows'); 160 $this->assertCount(3, $tree[1]->getChildren()[1]->getResultRows(), 'result rows'); 161 162 163 $this->assertEquals('a80', $tree[0]->getChildren()[0]->getResultRows()[0][0]->getValue(), 'Audi 80 expected'); 164 $this->assertEquals('pro 16', $tree[1]->getChildren()[0]->getResultRows()[0][0]->getValue(), 'Mac Pro 16 expected'); 165 } 166 167 /** 168 * Nest by three levels, the first one being multi-value 169 */ 170 public function testMultiThreeLevels() 171 { 172 $result = $this->makeResult($this->multiItems); 173 $nestedResult = new NestedResult($result); 174 $root = $nestedResult->getRoot(3); 175 $tree = $root->getChildren(); // nest: color, type, brand -> model 176 177 $this->assertCount(6, $tree, '6 root nodes of colors expected'); 178 179 // Values on the first level will be multi-values, thus returning arrays 180 $this->assertEquals('black', $tree[0]->getValueObject()->getValue()[0]); 181 $this->assertEquals('blue', $tree[1]->getValueObject()->getValue()[0]); 182 $this->assertEquals('gray', $tree[2]->getValueObject()->getValue()[0]); 183 $this->assertEquals('green', $tree[3]->getValueObject()->getValue()[0]); 184 $this->assertEquals('red', $tree[4]->getValueObject()->getValue()[0]); 185 $this->assertEquals('yellow', $tree[5]->getValueObject()->getValue()[0]); 186 187 // Results should now show up under multiple top-level nodes 188 $this->assertEquals('a80', 189 $tree[3] // green 190 ->getChildren()[0] // car 191 ->getChildren()[0] // audi 192 ->getResultRows()[0][0] // a80 193 ->getValue(), 194 'green car audi a80 expected' 195 ); 196 $this->assertEquals('a80', 197 $tree[5] // yellow 198 ->getChildren()[0] // car 199 ->getChildren()[0] // audi 200 ->getResultRows()[0][0] // a80 201 ->getValue(), 202 'yellow car audi a80 expected' 203 ); 204 } 205 206 public function testMultiHoles() 207 { 208 $result = $this->makeResult($this->multiHoleItems); 209 $nestedResult = new NestedResult($result); 210 $root = $nestedResult->getRoot(3); 211 $tree = $root->getChildren(); // nest: color, type, brand -> model 212 $this->assertCount(7, $tree, '6 root nodes of colors + 1 n/a expected'); // should have one n/a node 213 $this->assertCount(2, $tree[6]->getChildren(), 'top n/a node should have car, laptop'); 214 $this->assertCount(3, $tree[0]->getChildren(), 'black should have car,laptop,n/a'); 215 } 216 217 /** 218 * Nest by two multi value levels 219 */ 220 public function testMultiMultiTwoLevels() 221 { 222 $result = $this->makeResult($this->multiMultiItems); 223 $nestedResult = new NestedResult($result); 224 $root = $nestedResult->getRoot(2); 225 $tree = $root->getChildren(); // nest: material, color, * 226 227 $this->assertCount(3, $tree, '3 root nodes of material expected'); 228 $this->assertCount(1, $tree[0]->getChildren()[0]->getResultRows(), '1 metal black row expected'); 229 } 230 231 /** 232 * Nest by two multi value levels with indexing 233 */ 234 public function testMultiMultiTwoLevelsIndex() 235 { 236 $result = $this->makeResult($this->multiMultiItems); 237 $nestedResult = new NestedResult($result); 238 $root = $nestedResult->getRoot(2, 1); 239 $tree = $root->getChildren(); // nest: index, material, color, * 240 241 $this->assertCount(3, $tree, '3 root index nodes expected'); 242 $this->assertEquals('M', $tree[0]->getValueObject()->getValue(), 'M expected'); 243 $this->assertCount(1, $tree[0]->getChildren(), '1 metal sub node under M expected'); 244 } 245 246 /** 247 * Index a flat result with no multi values 248 */ 249 public function testSimpleIndex() 250 { 251 $result = $this->makeResult($this->simpleItems); 252 $nestedResult = new NestedResult($result); 253 $root = $nestedResult->getRoot(0, 2); 254 $tree = $root->getChildren(); 255 256 $this->assertCount(2, $tree, '2 root index nodes expected'); 257 $this->assertEquals('CA', $tree[0]->getValueObject()->getValue(), 'CA(r) index expected'); 258 $this->assertEquals('LA', $tree[1]->getValueObject()->getValue(), 'LA(ptop) index expected'); 259 260 $this->assertCount(6, $tree[0]->getResultRows(), '6 rows under CA expected'); 261 } 262 263 264 /** 265 * Index a flat result with multi values 266 */ 267 public function testMultiIndex() 268 { 269 $result = $this->makeResult($this->multiItems); 270 $nestedResult = new NestedResult($result); 271 $root = $nestedResult->getRoot(0, 2); 272 $tree = $root->getChildren(); 273 274 $this->assertCount(4, $tree, '4 root index nodes expected'); 275 $this->assertEquals('BL', $tree[0]->getValueObject()->getValue(), 'BL(ack|blue) index expected'); 276 277 $this->assertCount(4, $tree[0]->getResultRows(), '4 rows under BL expected'); 278 } 279} 280