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', 'inspiron'],
30        ['laptop', 'dell', 'latitude'],
31        ['laptop', 'bmw', '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     * Don't nest at all
73     */
74    public function testSimpleZeroLevel()
75    {
76        $result = $this->createAggregationResult($this->simpleItems);
77        $nestedResult = new NestedResult($result);
78        $root = $nestedResult->getRoot(0);
79
80        $this->assertCount(0, $root->getChildren(true), 'no children expected');
81        $this->assertCount(12, $root->getResultRows(), '12 result rows expected');
82    }
83
84    /**
85     * Nest by the first level, no multi values
86     */
87    public function testSimpleOneLevel()
88    {
89        $result = $this->createAggregationResult($this->simpleItems);
90        $nestedResult = new NestedResult($result);
91        $root = $nestedResult->getRoot(1);
92        $tree = $root->getChildren(true);
93
94        $this->assertCount(2, $tree, '2 root nodes expected');
95        $this->assertEquals('car', $tree[0]->getValueObject()->getValue());
96        $this->assertEquals('laptop', $tree[1]->getValueObject()->getValue());
97
98        $this->assertCount(0, $tree[0]->getChildren(true), 'no children expected');
99        $this->assertCount(0, $tree[1]->getChildren(true), 'no children expected');
100
101        $this->assertCount(6, $tree[0]->getResultRows(), 'result rows');
102        $this->assertCount(6, $tree[1]->getResultRows(), 'result rows');
103
104        $this->assertEquals('a80', $tree[0]->getResultRows()[0][1]->getValue(), 'Audi 80 expected');
105        $this->assertEquals('pro 16', $tree[1]->getResultRows()[0][1]->getValue(), 'Mac Pro 16 expected');
106    }
107
108
109    /**
110     * Nest by two levels, no multi values
111     */
112    public function testSimpleTwoLevels()
113    {
114        $result = $this->createAggregationResult($this->simpleItems);
115        $nestedResult = new NestedResult($result);
116        $root = $nestedResult->getRoot(2);
117        $tree = $root->getChildren(true);
118
119        $this->assertCount(2, $tree, '2 root nodes expected');
120        $this->assertEquals('car', $tree[0]->getValueObject()->getValue());
121        $this->assertEquals('laptop', $tree[1]->getValueObject()->getValue());
122
123        $this->assertCount(2, $tree[0]->getChildren(true), '2 car brands expected');
124        $this->assertCount(3, $tree[1]->getChildren(true), '3 laptop brands expected');
125
126        $this->assertCount(3, $tree[0]->getChildren(true)[0]->getResultRows(), '3 audis expected');
127        $this->assertCount(3, $tree[0]->getChildren(true)[1]->getResultRows(), '3 bmw expected');
128        $this->assertCount(3, $tree[1]->getChildren(true)[0]->getResultRows(), '3 apple expected');
129        $this->assertCount(1, $tree[1]->getChildren(true)[1]->getResultRows(), '1 bmw expected');
130        $this->assertCount(2, $tree[1]->getChildren(true)[2]->getResultRows(), '2 dell expected');
131
132
133        $this->assertEquals('a80', $tree[0]->getChildren(true)[0]->getResultRows()[0][0]->getValue(), 'Audi 80 expected');
134        $this->assertEquals('pro 16', $tree[1]->getChildren(true)[0]->getResultRows()[0][0]->getValue(), 'Mac Pro 16 expected');
135    }
136
137    /**
138     * Nest by three levels, the first one being multi-value
139     */
140    public function testMultiThreeLevels()
141    {
142        $result = $this->createAggregationResult($this->multiItems);
143        $nestedResult = new NestedResult($result);
144        $root = $nestedResult->getRoot(3);
145        $tree = $root->getChildren(true); // nest: color, type, brand -> model
146
147        $this->assertCount(6, $tree, '6 root nodes of colors expected');
148
149        // Values on the first level will be multi-values, thus returning arrays
150        $this->assertEquals('black', $tree[0]->getValueObject()->getValue()[0]);
151        $this->assertEquals('blue', $tree[1]->getValueObject()->getValue()[0]);
152        $this->assertEquals('gray', $tree[2]->getValueObject()->getValue()[0]);
153        $this->assertEquals('green', $tree[3]->getValueObject()->getValue()[0]);
154        $this->assertEquals('red', $tree[4]->getValueObject()->getValue()[0]);
155        $this->assertEquals('yellow', $tree[5]->getValueObject()->getValue()[0]);
156
157        // Results should now show up under multiple top-level nodes
158        $this->assertEquals('a80',
159            $tree[3] // green
160            ->getChildren(true)[0] // car
161            ->getChildren(true)[0] // audi
162            ->getResultRows()[0][0] // a80
163            ->getValue(),
164            'green car audi a80 expected'
165        );
166        $this->assertEquals('a80',
167            $tree[5] // yellow
168            ->getChildren(true)[0] // car
169            ->getChildren(true)[0] // audi
170            ->getResultRows()[0][0] // a80
171            ->getValue(),
172            'yellow car audi a80 expected'
173        );
174    }
175
176    public function testMultiHoles()
177    {
178        $result = $this->createAggregationResult($this->multiHoleItems);
179        $nestedResult = new NestedResult($result);
180        $root = $nestedResult->getRoot(3);
181        $tree = $root->getChildren(true); // nest: color, type, brand -> model
182        $this->assertCount(7, $tree, '6 root nodes of colors + 1 n/a expected');  // should have one n/a node
183        $this->assertCount(2, $tree[6]->getChildren(true), 'top n/a node should have car, laptop');
184        $this->assertCount(3, $tree[0]->getChildren(true), 'black should have car,laptop,n/a');
185    }
186
187    /**
188     * Nest by two multi value levels
189     */
190    public function testMultiMultiTwoLevels()
191    {
192        $result = $this->createAggregationResult($this->multiMultiItems);
193        $nestedResult = new NestedResult($result);
194        $root = $nestedResult->getRoot(2);
195        $tree = $root->getChildren(true); // nest: material, color, *
196
197        $this->assertCount(3, $tree, '3 root nodes of material expected');
198        $this->assertCount(1, $tree[0]->getChildren(true)[0]->getResultRows(), '1 metal black row expected');
199    }
200
201    /**
202     * Nest by two multi value levels with indexing
203     */
204    public function testMultiMultiTwoLevelsIndex()
205    {
206        $result = $this->createAggregationResult($this->multiMultiItems);
207        $nestedResult = new NestedResult($result);
208        $root = $nestedResult->getRoot(2, 1);
209        $tree = $root->getChildren(true); // nest: index, material, color, *
210
211        $this->assertCount(3, $tree, '3 root index nodes  expected');
212        $this->assertEquals('M', $tree[0]->getValueObject()->getValue(), 'M expected');
213        $this->assertCount(1, $tree[0]->getChildren(true), '1 metal sub node under M expected');
214    }
215
216    /**
217     * Index a flat result with no multi values
218     */
219    public function testSimpleIndex()
220    {
221        $result = $this->createAggregationResult($this->simpleItems);
222        $nestedResult = new NestedResult($result);
223        $root = $nestedResult->getRoot(0, 2);
224        $tree = $root->getChildren(true);
225
226        $this->assertCount(2, $tree, '2 root index nodes  expected');
227        $this->assertEquals('CA', $tree[0]->getValueObject()->getValue(), 'CA(r) index expected');
228        $this->assertEquals('LA', $tree[1]->getValueObject()->getValue(), 'LA(ptop) index expected');
229
230        $this->assertCount(6, $tree[0]->getResultRows(), '6 rows under CA expected');
231    }
232
233
234    /**
235     * Index a flat result with multi values
236     */
237    public function testMultiIndex()
238    {
239        $result = $this->createAggregationResult($this->multiItems);
240        $nestedResult = new NestedResult($result);
241        $root = $nestedResult->getRoot(0, 2);
242        $tree = $root->getChildren(true);
243
244        $this->assertCount(4, $tree, '4 root index nodes  expected');
245        $this->assertEquals('BL', $tree[0]->getValueObject()->getValue(), 'BL(ack|blue) index expected');
246
247        $this->assertCount(4, $tree[0]->getResultRows(), '4 rows under BL expected');
248    }
249}
250