1<?php
2
3namespace dokuwiki\plugin\struct\test;
4
5use dokuwiki\plugin\struct\meta\ValidationException;
6use dokuwiki\plugin\struct\meta\Value;
7use dokuwiki\plugin\struct\test\mock\Search;
8use dokuwiki\plugin\struct\types\Decimal;
9
10/**
11 * Testing the Decimal Type
12 *
13 * @group plugin_struct
14 * @group plugins
15 */
16class Type_Decimal_struct_test extends StructTest
17{
18
19    /**
20     * Provides failing validation data
21     *
22     * @return array
23     */
24    public function validateFailProvider()
25    {
26        return array(
27            // same as integer:
28            array('foo', '', ''),
29            array('foo222', '', ''),
30            array('-5', '0', ''),
31            array('5', '', '0'),
32            array('500', '100', '200'),
33            array('50', '100', '200'),
34            // decimal specifics
35            array('5.5', '5.6', ''),
36            array('5,5', '5.6', ''),
37            array('-5.5', '-5.4', ''),
38            array('-5,5', '-5.4', ''),
39        );
40    }
41
42    /**
43     * Provides successful validation data
44     *
45     * @return array
46     */
47    public function validateSuccessProvider()
48    {
49        return array(
50            // same as integer
51            array('0', '', ''),
52            array('-5', '', ''),
53            array('5', '', ''),
54            array('5', '0', ''),
55            array('-5', '', '0'),
56            array('150', '100', '200'),
57            // decimal specifics
58            array('5.5', '', ''),
59            array('5,5', '', ''),
60            array('-5.5', '', ''),
61            array('-5,5', '', ''),
62            array('5.5', '4.5', ''),
63            array('5,5', '4.5', ''),
64            array('-5.5', '', '4.5'),
65            array('-5,5', '', '4.5'),
66            array('5.5645000', '', ''),
67            // boundaries
68            array('0', '0', ''),
69            array('0', '', '0'),
70            array('5', '5', ''),
71            array('5', '', '5'),
72            array('0', '0.0', ''),
73            array('0', '', '0.0'),
74            array('5.0', '5.0', ''),
75            array('5.0', '', '5.0'),
76        );
77    }
78
79
80    /**
81     * @dataProvider validateFailProvider
82     */
83    public function test_validate_fail($value, $min, $max)
84    {
85        $this->expectException(ValidationException::class);
86        $decimal = new Decimal(array('min' => $min, 'max' => $max));
87        $decimal->validate($value);
88    }
89
90    /**
91     * @dataProvider validateSuccessProvider
92     */
93    public function test_validate_success($value, $min, $max, $decpoint = '.')
94    {
95        $decimal = new Decimal(array('min' => $min, 'max' => $max));
96        $decimal->validate($value);
97        $this->assertTrue(true); // we simply check that no exceptions are thrown
98    }
99
100
101    public function valueProvider()
102    {
103        return array(
104            // $value, $expect, $roundto, $decpoint, $thousands, $trimzeros, $prefix='', $postfix='', $engineering = false
105            array('5000', '5 000,00', '2', ',', ' ', false),
106            array('5000', '5 000', '2', ',', ' ', true),
107            array('5000', '5 000', '0', ',', ' ', false),
108            array('5000', '5 000', '0', ',', ' ', true),
109            array('5000', '5 000', '-1', ',', ' ', false),
110            array('5000', '5 000', '-1', ',', ' ', true),
111
112            array('-0.55600', '-0,56', '2', ',', ' ', false),
113            array('-0.55600', '-0,55600', '-1', ',', ' ', false),
114            array('-0.55600', '-0,556', '-1', ',', ' ', true),
115            array('-0.55600', '-0,5560', '4', ',', ' ', false),
116            array('-0.55600', '-0,556', '4', ',', ' ', true),
117
118            array('-0.55600', '$ -0,556', '4', ',', ' ', true, '$ '),
119            array('-0.55600', '-0,556 EUR', '4', ',', ' ', true, '', ' EUR'),
120
121            //engineering notation
122            array('1e-18', '1'."\xE2\x80\xAF".'a', '-1', ',', ' ', true, '', '', true),
123            array('1e-15', '1'."\xE2\x80\xAF".'f', '-1', ',', ' ', true, '', '', true),
124            array('1e-12', '1'."\xE2\x80\xAF".'p', '-1', ',', ' ', true, '', '', true),
125            array('1e-9',  '1'."\xE2\x80\xAF".'n', '-1', ',', ' ', true, '', '', true),
126            array('1e-6',  '1'."\xE2\x80\xAF".'µ', '-1', ',', ' ', true, '', '', true),
127            array('1e-3',  '1'."\xE2\x80\xAF".'m', '-1', ',', ' ', true, '', '', true),
128
129            array('1e3',  '1'."\xE2\x80\xAF".'k', '-1', ',', ' ', true, '', '', true),
130            array('1e6',  '1'."\xE2\x80\xAF".'M', '-1', ',', ' ', true, '', '', true),
131            array('1e9',  '1'."\xE2\x80\xAF".'G', '-1', ',', ' ', true, '', '', true),
132            array('1e12', '1'."\xE2\x80\xAF".'T', '-1', ',', ' ', true, '', '', true),
133
134            array('1e4', '10'. "\xE2\x80\xAF".'k', '-1', ',', ' ', true, '', '', true),
135            array('1e5', '100'."\xE2\x80\xAF".'k', '-1', ',', ' ', true, '', '', true),
136
137            array('1e-4', '100'."\xE2\x80\xAF".'µ', '-1', ',', ' ', true, '', '', true),
138            array('1e-5', '10'. "\xE2\x80\xAF".'µ', '-1', ',', ' ', true, '', '', true),
139
140            //test behaviour if number exceeds prefix array
141            array('1e15',  '1000'. "\xE2\x80\xAF".'T', '-1', ',', ' ', true, '', '', true),
142            array('1e-21', '0.001'."\xE2\x80\xAF".'a', '-1', ',', ' ', true, '', '', true),
143
144        );
145    }
146
147    /**
148     * @dataProvider valueProvider
149     */
150    public function test_renderValue($value, $expect, $roundto, $decpoint, $thousands, $trimzeros, $prefix = '', $postfix = '', $engineering = false)
151    {
152        $decimal = new Decimal(array(
153            'roundto' => $roundto,
154            'decpoint' => $decpoint,
155            'thousands' => $thousands,
156            'trimzeros' => $trimzeros,
157            'prefix' => $prefix,
158            'postfix' => $postfix,
159            'engineering' => $engineering
160        ));
161        $R = new \Doku_Renderer_xhtml();
162        $R->doc = '';
163        $decimal->renderValue($value, $R, 'xhtml');
164        $this->assertEquals($expect, $R->doc);
165    }
166
167    public function test_sort()
168    {
169        $this->loadSchemaJSON('decimal');
170        $this->waitForTick();
171        $this->saveData('page1', 'decimal', array('field' => '5000'));
172        $this->saveData('page2', 'decimal', array('field' => '5000.001'));
173        $this->saveData('page3', 'decimal', array('field' => '900.5'));
174        $this->saveData('page4', 'decimal', array('field' => '1.5'));
175
176        $search = new Search();
177        $search->addSchema('decimal');
178        $search->addColumn('%pageid%');
179        $search->addColumn('field');
180        $search->addSort('field', true);
181        /** @var Value[][] $result */
182        $result = $search->execute();
183
184        $this->assertEquals(4, count($result));
185        $this->assertEquals('page4', $result[0][0]->getValue());
186        $this->assertEquals('page3', $result[1][0]->getValue());
187        $this->assertEquals('page1', $result[2][0]->getValue());
188        $this->assertEquals('page2', $result[3][0]->getValue());
189    }
190
191    public function test_filter()
192    {
193        $this->loadSchemaJSON('decimal');
194        $this->waitForTick();
195        $this->saveData('page1', 'decimal', array('field' => '5000'));
196        $this->saveData('page2', 'decimal', array('field' => '5000.001'));
197        $this->saveData('page3', 'decimal', array('field' => '900.5'));
198        $this->saveData('page4', 'decimal', array('field' => '1.5'));
199
200        $search = new Search();
201        $search->addSchema('decimal');
202        $search->addColumn('%pageid%');
203        $search->addColumn('field');
204        $search->addFilter('field', '800', '>', 'AND');
205        $search->addSort('field', true);
206        /** @var Value[][] $result */
207        $result = $search->execute();
208
209        $this->assertEquals(3, count($result));
210        $this->assertEquals('page3', $result[0][0]->getValue());
211        $this->assertEquals('page1', $result[1][0]->getValue());
212        $this->assertEquals('page2', $result[2][0]->getValue());
213    }
214
215}
216