Completed
Push — master ( a0c1a6...f8ae7f )
by Fwolf
03:26
created

CodeDictionaryTest::testSetWithEmptyValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 10
rs 9.4285
1
<?php
2
namespace FwlibTest\Db;
3
4
use Fwlib\Bridge\Adodb;
5
use Fwlib\Db\CodeDictionary;
6
use Fwolf\Wrapper\PHPUnit\PHPUnitTestCase;
7
use PHPUnit_Framework_MockObject_MockObject as MockObject;
8
9
/**
10
 * @SuppressWarnings(PHPMD.TooManyMethods)
11
 *
12
 * @copyright   Copyright 2011-2015 Fwolf
13
 * @license     http://www.gnu.org/licenses/lgpl.html LGPL-3.0+
14
 */
15
class CodeDictionaryTest extends PHPUnitTestCase
16
{
17
    /**
18
     * Db mock return value
19
     *
20
     * @var bool
21
     */
22
    public static $isConnected;
23
24
    /**
25
     * @var bool
26
     */
27
    public static $isDbMysql;
28
29
30
    /**
31
     * @return  MockObject|Adodb
32
     */
33
    protected function buildDbMock()
34
    {
35
        $dbConn = $this->getMockBuilder(
36
            Adodb::class
37
        )
38
            ->setMethods([
39
                'getProfile',
40
                'getSqlDelimiter',
41
                'getSqlTruncate',
42
                'getSqlTransBegin',
43
                'getSqlTransCommit',
44
                'isConnected',
45
                'isDbMysql',
46
                'quoteValue',
47
            ])
48
            ->disableOriginalConstructor()
49
            ->getMock();
50
51
        $dbConn->expects($this->any())
52
            ->method('getProfile')
53
            ->will($this->returnValue(['lang' => '{profileLang}']));
54
55
        $dbConn->expects($this->any())
56
            ->method('getSqlDelimiter')
57
            ->will($this->returnValue("{sqlDelimiter}\n"));
58
59
        $dbConn->expects($this->any())
60
            ->method('getSqlTransBegin')
61
            ->will($this->returnValue("{sqlTransBegin}\n"));
62
63
        $dbConn->expects($this->any())
64
            ->method('getSqlTransCommit')
65
            ->will($this->returnValue("{sqlTransCommit}\n"));
66
67
        $dbConn->expects($this->any())
68
            ->method('getSqlTruncate')
69
            ->will($this->returnValue('{sqlTruncate}'));
70
71
        $dbConn->expects($this->any())
72
            ->method('isConnected')
73
            ->will($this->returnCallback(function () {
74
                return CodeDictionaryTest::$isConnected;
75
            }));
76
77
        $dbConn->expects($this->any())
78
            ->method('isDbMysql')
79
            ->will($this->returnCallback(function () {
80
                return CodeDictionaryTest::$isDbMysql;
81
            }));
82
83
        $dbConn->expects($this->any())
84
            ->method('quoteValue')
85
            ->will($this->returnValue('{quoteValue}'));
86
87
        return $dbConn;
88
    }
89
90
91
    /**
92
     * @return  MockObject|CodeDictionary
93
     */
94
    protected function buildMock()
95
    {
96
        $dictionary = new CodeDictionary();
97
98
        $dictionary->set([
99
            [123, 'a'],
100
            ['bac', 2],
101
            [321, 'c'],
102
        ]);
103
104
        return $dictionary;
105
    }
106
107
108
    public function testAccessors()
109
    {
110
        $dictionary = new CodeDictionary;
111
112
        $dictionary->setColumns(['a', 'b']);
113
        $this->assertEqualArray(['a', 'b'], $dictionary->getColumns());
114
115
        $dictionary->setPrimaryKey('a');
116
        $this->assertEquals('a', $dictionary->getPrimaryKey());
117
118
        $dictionary->setTable('dummyTable');
119
        $this->assertEquals('dummyTable', $dictionary->getTable());
120
    }
121
122
123
    public function testFixDictionaryIndex()
124
    {
125
        $arrayWithoutIndex = [
126
            [123, 'a'],
127
            ['bac', 2],
128
            [321, 'c'],
129
        ];
130
        $arrayWithIndex = [
131
            123   => [
132
                'code'  => 123,
133
                'title' => 'a',
134
            ],
135
            'bac' => [
136
                'code'  => 'bac',
137
                'title' => 2,
138
            ],
139
            321   => [
140
                'code'  => 321,
141
                'title' => 'c',
142
            ],
143
        ];
144
145
        $dictionary = $this->buildMock();
146
147
        // Simulate $dictionary define by assign value to it
148
        $this->reflectionSet($dictionary, 'dictionary', $arrayWithoutIndex);
149
        // Then call constructor to simulate new operate
150
        $this->reflectionCall($dictionary, '__construct');
151
152
        $this->assertEqualArray($arrayWithIndex, $dictionary->getAll());
153
    }
154
155
156
    public function testGet()
157
    {
158
        $dictionary = $this->buildMock();
159
160
        $this->assertEquals(null, $dictionary->get(null));
161
        $this->assertEquals(null, $dictionary->getMultiple([]));
162
        $this->assertEquals(null, $dictionary->get('notExistKey'));
163
        $this->assertEquals(
164
            ['notExistKey' => null],
165
            $dictionary->getMultiple(['notExistKey'])
166
        );
167
        $this->assertEquals('a', $dictionary->get(123));
168
        $this->assertEquals(2, $dictionary->get('bac'));
169
        $this->assertEquals(
170
            [123 => 'a', 321 => 'c'],
171
            $dictionary->getMultiple([123, 321])
172
        );
173
    }
174
175
176
    public function testGetSingleColumn()
177
    {
178
        $dictionary = $this->buildMock();
179
        $this->reflectionSet($dictionary, 'dictionary', []);
180
181
        $dictionary->setColumns(['a', 'b', 'c'])
182
            ->setPrimaryKey('a')
183
            ->set([
184
                ['a' => 1, 'b' => 2, 'c' => 3],
185
                ['a' => 10, 'b' => 20, 'c' => 30],
186
                ['a' => 100, 'b' => 200, 'c' => 300],
187
            ]);
188
189
        $this->assertEqualArray(
190
            $dictionary->getSingleColumn('c'),
191
            [1 => 3, 10 => 30, 100 => 300]
192
        );
193
    }
194
195
196
    /**
197
     * @expectedException \Fwlib\Db\Exception\InvalidColumnException
198
     */
199
    public function testGetSingleColumnWithInvalidColumn()
200
    {
201
        $dictionary = $this->buildMock();
202
203
        $dictionary->getSingleColumn('notExist');
204
    }
205
206
207
    /**
208
     * @expectedException \Exception
209
     * @expectedExceptionMessage Database not connected
210
     */
211
    public function testGetSqlWithDbNotConnected()
212
    {
213
        $dictionary = $this->buildMock();
214
        self::$isConnected = false;
215
216
        $dictionary->getSql($this->buildDbMock());
0 ignored issues
show
Bug introduced by
It seems like $this->buildDbMock() targeting FwlibTest\Db\CodeDictionaryTest::buildDbMock() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Fwlib\Db\CodeDictionary::getSql() does only seem to accept object<Fwlib\Bridge\Adodb>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
217
    }
218
219
220
    public function testGetSqlWithNoTableName()
221
    {
222
        $dictionary = $this->buildMock();
223
224
        $dictionary->setTable('');
225
226
        $this->assertEmpty($dictionary->getSql($this->buildDbMock()));
0 ignored issues
show
Bug introduced by
It seems like $this->buildDbMock() targeting FwlibTest\Db\CodeDictionaryTest::buildDbMock() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Fwlib\Db\CodeDictionary::getSql() does only seem to accept object<Fwlib\Bridge\Adodb>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
227
    }
228
229
230
    public function testGetSqlWithTable()
231
    {
232
        $dictionary = $this->buildMock();
233
234
        self::$isConnected = true;
235
        self::$isDbMysql = true;
236
237
        /** @noinspection SpellCheckingInspection */
238
        $sqlExpected = 'SET NAMES \'{PROFILELANG}\'{sqlDelimiter}
239
{sqlTransBegin}
240
TRUNCATE TABLE code_dictionary{sqlDelimiter}
241
{sqlTransCommit}
242
{sqlTransBegin}
243
INSERT INTO code_dictionary (code, title) VALUES ({quoteValue}, {quoteValue}){sqlDelimiter}
244
INSERT INTO code_dictionary (code, title) VALUES ({quoteValue}, {quoteValue}){sqlDelimiter}
245
INSERT INTO code_dictionary (code, title) VALUES ({quoteValue}, {quoteValue}){sqlDelimiter}
246
{sqlTransCommit}
247
';
248
249
        $sql = $dictionary->getSql($this->buildDbMock());
0 ignored issues
show
Bug introduced by
It seems like $this->buildDbMock() targeting FwlibTest\Db\CodeDictionaryTest::buildDbMock() can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Fwlib\Db\CodeDictionary::getSql() does only seem to accept object<Fwlib\Bridge\Adodb>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
250
251
        $this->assertEquals($sqlExpected, $sql);
252
        $this->assertEquals(3, preg_match_all('/INSERT INTO/', $sql, $match));
253
        $this->assertEquals(1, preg_match_all('/TRUNCATE/', $sql, $match));
254
    }
255
256
257
    public function testSearch()
258
    {
259
        $dictionary = $this->buildMock();
260
        $code = CodeDictionary::COL_CODE;
261
        $title = CodeDictionary::COL_TITLE;
262
263
        $this->assertEquals(
264
            ['bac' => [$code => 'bac', $title => 2]],
265
            $dictionary->search(function ($row) {
266
                return !is_numeric($row[CodeDictionary::COL_CODE]);
267
            })
268
        );
269
270
        $this->assertEquals(
271
            [
272
                123 => [$code => 123, $title => 'a'],
273
                321 => [$code => 321, $title => 'c'],
274
            ],
275
            $dictionary->search(function ($row) {
276
                return '2' == substr($row[CodeDictionary::COL_CODE], 1, 1);
277
            })
278
        );
279
280
        $this->assertEquals(
281
            [
282
                321 => [$code => 321, $title => 'c'],
283
            ],
284
            $dictionary->search(function ($row) {
285
                return 'c' == $row[CodeDictionary::COL_TITLE] &&
286
                '2' == substr($row[CodeDictionary::COL_CODE], 1, 1);
287
            })
288
        );
289
290
        // Search with assign cols
291
        $this->assertEquals(
292
            [321 => 'c'],
293
            $dictionary->search(function ($row) {
294
                return 'c' == $row[CodeDictionary::COL_TITLE];
295
            }, $title)
296
        );
297
298
        // Search on empty dictionary will return empty array
299
        $this->reflectionSet($dictionary, 'dictionary', []);
300
        $this->assertEqualArray(
301
            [],
302
            $dictionary->search('time')
303
        );
304
    }
305
306
307
    public function testSet()
308
    {
309
        $dictionary = $this->buildMock();
310
311
        $dictionary->set(['foo', 'bar']);
312
        $this->assertEquals(4, count($dictionary->getAll()));
313
    }
314
315
316
    /**
317
     * @expectedException \Exception
318
     * @expectedExceptionMessage Primary key value is empty or not set
319
     */
320
    public function testSetWithEmptyPk()
321
    {
322
        $dictionary = $this->buildMock();
323
324
        $dictionary->set(['', 'bar']);
325
    }
326
327
328
    /**
329
     * @expectedException \Exception
330
     * @expectedExceptionMessage contain all columns
331
     */
332
    public function testSetWithEmptyRowInData()
333
    {
334
        $dictionary = $this->buildMock();
335
336
        $dictionary->set([[null], ['foo', 'bar']]);
337
    }
338
339
340
    public function testSetWithEmptyValue()
341
    {
342
        $dictionary = $this->buildMock();
343
344
        $dictionaryBefore = $dictionary->getAll();
345
        $dictionary->set([]);
346
        $dictionaryAfter = $dictionary->getAll();
347
348
        $this->assertEqualArray($dictionaryBefore, $dictionaryAfter);
349
    }
350
351
352
    /**
353
     * @expectedException \Exception
354
     * @expectedExceptionMessage Dictionary column not defined
355
     */
356
    public function testSetWithNoColumn()
357
    {
358
        $dictionary = $this->buildMock();
359
360
        $dictionary->setColumns([]);
361
362
        $dictionary->set(['foo' => 'bar']);
363
    }
364
365
366
    /**
367
     * @expectedException \Exception
368
     * @expectedExceptionMessage include primary key
369
     */
370
    public function testSetWithPrimaryKeyNotInColumn()
371
    {
372
        $dictionary = $this->buildMock();
373
374
        $dictionary->setPrimaryKey('notExistColumn');
375
376
        $dictionary->set(['foo' => 'bar']);
377
    }
378
}
379