DBObjectTest::testForceInsert()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 3
b 0
f 0
nc 1
nop 0
dl 0
loc 17
rs 9.9332
1
<?php
2
require_once 'stubs/Category.php';
3
4
/**
5
 * @SuppressWarnings("StaticAccess")
6
 */
7
class DBObjectTest extends \PHPUnit\Framework\TestCase
8
{
9
    protected $tableName = 'users';
10
    public function testContructor()
11
    {
12
        $classname = '\Suricate\DBObject';
13
14
        // Get mock, without the constructor being called
15
        $mock = $this->getMockBuilder($classname)
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\MockOb...ckBuilder::setMethods() has been deprecated: https://github.com/sebastianbergmann/phpunit/pull/3687 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

15
        $mock = /** @scrutinizer ignore-deprecated */ $this->getMockBuilder($classname)

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
16
            ->disableOriginalConstructor()
17
            ->setMethods(['setRelations'])
18
            ->getMockForAbstractClass();
19
20
        // set expectations for constructor calls
21
        $mock->expects($this->once())->method('setRelations');
22
23
        // now call the constructor
24
        $reflectedClass = new ReflectionClass($classname);
25
        $constructor = $reflectedClass->getConstructor();
26
        $constructor->invoke($mock);
27
    }
28
29
    public function testGetTableName()
30
    {
31
        $testName = 'my_sql_table';
32
33
        $testDBO = new \Suricate\DBObject();
34
        self::mockProperty($testDBO, 'tableName', $testName);
35
        $this->assertEquals($testName, $testDBO->getTableName());
36
    }
37
38
    public function testStaticTableName()
39
    {
40
        $this->assertEquals('categories', Category::tableName());
41
    }
42
43
    public function testGetTableIndex()
44
    {
45
        $testIndex = 'id';
46
47
        $testDBO = new \Suricate\DBObject();
48
        self::mockProperty($testDBO, 'tableIndex', $testIndex);
49
        $this->assertEquals($testIndex, $testDBO->getTableIndex());
50
    }
51
52
    public function testStaticTableIndex()
53
    {
54
        $this->assertEquals('id', Category::tableIndex());
55
    }
56
57
    public function testGetDBConfig()
58
    {
59
        $testConfigName = 'my_config';
60
61
        $testDBO = new \Suricate\DBObject();
62
        self::mockProperty($testDBO, 'DBConfig', $testConfigName);
63
        $this->assertEquals($testConfigName, $testDBO->getDBConfig());
64
    }
65
66
    public function testUndefinedGet()
67
    {
68
        $testDBO = new \Suricate\DBObject();
69
        self::mockProperty($testDBO, 'dbVariables', [
70
            'id',
71
            'name',
72
            'last_update'
73
        ]);
74
        $this->expectException(\InvalidArgumentException::class);
75
76
        $testDBO->undefinedVar;
0 ignored issues
show
Bug Best Practice introduced by
The property undefinedVar does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
77
    }
78
79
    public function testDBProperty()
80
    {
81
        $testDBO = new \Suricate\DBObject();
82
        $testDBO->regularProperty = 42;
0 ignored issues
show
Bug Best Practice introduced by
The property regularProperty does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
83
        self::mockProperty($testDBO, 'dbVariables', [
84
            'id',
85
            'name',
86
            'not_loaded_var'
87
        ]);
88
        self::mockProperty($testDBO, 'dbValues', [
89
            'id' => 1,
90
            'name' => 'test name'
91
        ]);
92
        $this->assertEquals($testDBO->id, 1);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
93
        $this->assertNotEquals($testDBO->name, 'test name edited');
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
94
        $this->assertNull($testDBO->not_loaded_var);
0 ignored issues
show
Bug Best Practice introduced by
The property not_loaded_var does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
95
96
        $this->assertTrue($testDBO->isDBVariable('id'));
97
        $this->assertFalse($testDBO->isDBVariable('regularProperty'));
98
99
        $this->assertTrue($testDBO->propertyExists('regularProperty'));
100
        $this->assertTrue($testDBO->propertyExists('id'));
101
        $this->assertFalse($testDBO->propertyExists('unknownProperty'));
102
    }
103
104
    public function testIsset()
105
    {
106
        $testDBO = new \Suricate\DBObject();
107
        self::mockProperty($testDBO, 'dbVariables', [
108
            'id',
109
            'name',
110
            'not_loaded_var'
111
        ]);
112
        self::mockProperty($testDBO, 'dbValues', [
113
            'id' => 1,
114
            'name' => 'test name'
115
        ]);
116
117
        $this->assertTrue(isset($testDBO->id));
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
118
        $this->assertFalse(isset($testDBO->undefVar));
0 ignored issues
show
Bug Best Practice introduced by
The property undefVar does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
119
    }
120
121
    public function testIsLoaded()
122
    {
123
        $testIndex = 'id';
124
125
        $testDBO = new \Suricate\DBObject();
126
        self::mockProperty($testDBO, 'tableIndex', $testIndex);
127
        self::mockProperty($testDBO, 'dbVariables', [
128
            $testIndex,
129
            'name',
130
            'not_loaded_var'
131
        ]);
132
        $this->assertFalse($testDBO->isLoaded());
133
134
        self::mockProperty($testDBO, 'dbValues', [
135
            $testIndex => 1,
136
            'name' => 'test name'
137
        ]);
138
        $this->assertFalse($testDBO->isLoaded());
139
140
        $this->setupData();
141
        $dbo = $this->getDBOject();
142
        $this->assertFalse($dbo->isLoaded());
143
        $dbo->load(1);
144
        $this->assertTrue($dbo->isLoaded());
145
        $dbo->load(999);
146
        $this->assertFalse($dbo->isLoaded());
147
    }
148
149
    public function testSetLoaded()
150
    {
151
        $testIndex = 'id';
152
153
        $testDBO = new \Suricate\DBObject();
154
        self::mockProperty($testDBO, 'tableIndex', $testIndex);
155
        self::mockProperty($testDBO, 'dbVariables', [
156
            $testIndex,
157
            'name',
158
            'not_loaded_var'
159
        ]);
160
        $this->assertFalse($testDBO->isLoaded());
161
        $testDBO->setLoaded();
162
        $this->assertTrue($testDBO->isLoaded());
163
    }
164
165
    public function testProtected()
166
    {
167
        $testDBO = Category::instanciate([
168
            'id' => 1,
169
            'name' => 'test record'
170
        ]);
171
        $reflector = new ReflectionClass(Category::class);
172
        $property = $reflector->getProperty('protectedValues');
173
        $property->setAccessible(true);
174
        $this->assertSame([], $property->getValue($testDBO));
175
        $this->assertNull($testDBO->unloadable);
0 ignored issues
show
Bug Best Practice introduced by
The property unloadable does not exist on Category. Since you implemented __get, consider adding a @property annotation.
Loading history...
176
177
        $reflector = new ReflectionClass(Category::class);
178
        $property = $reflector->getProperty('protectedValues');
179
        $property->setAccessible(true);
180
        $this->assertSame([], $property->getValue($testDBO));
181
182
        $reflector = new ReflectionClass(Category::class);
183
        $property = $reflector->getProperty('loadedProtectedVariables');
184
        $property->setAccessible(true);
185
        $this->assertSame([], $property->getValue($testDBO));
186
187
        $this->assertSame(42, $testDBO->prot_var);
188
        $property = $reflector->getProperty('protectedValues');
189
        $property->setAccessible(true);
190
        $this->assertSame(['prot_var' => 42], $property->getValue($testDBO));
191
192
        $reflector = new ReflectionClass(Category::class);
193
        $property = $reflector->getProperty('loadedProtectedVariables');
194
        $property->setAccessible(true);
195
        $this->assertSame(['prot_var' => true], $property->getValue($testDBO));
196
    }
197
    public function testInstanciate()
198
    {
199
        $testDBO = Category::instanciate([
200
            'id' => 1,
201
            'name' => 'test record'
202
        ]);
203
204
        $reflector = new ReflectionClass(Category::class);
205
        $property = $reflector->getProperty('dbValues');
206
        $property->setAccessible(true);
207
        $this->assertEquals(
208
            [
209
                'id' => 1,
210
                'name' => 'test record'
211
            ],
212
            $property->getValue($testDBO)
213
        );
214
215
        $this->assertFalse($testDBO->isLoaded());
216
    }
217
218
    public function testHydrate()
219
    {
220
        $testDBO = new \Suricate\DBObject();
221
        $testDBO->realProperty = '';
0 ignored issues
show
Bug Best Practice introduced by
The property realProperty does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
222
223
        self::mockProperty($testDBO, 'dbVariables', ['id', 'name']);
224
        $testDBO->hydrate([
225
            'id' => 1,
226
            'name' => 'test record',
227
            'add_column' => 'test value',
228
            'realProperty' => 'my string'
229
        ]);
230
231
        $this->assertEquals($testDBO->realProperty, 'my string');
0 ignored issues
show
Bug Best Practice introduced by
The property realProperty does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
232
233
        $reflector = new ReflectionClass(get_class($testDBO));
234
        $property = $reflector->getProperty('dbValues');
235
        $property->setAccessible(true);
236
        $this->assertEquals(
237
            [
238
                'id' => 1,
239
                'name' => 'test record'
240
            ],
241
            $property->getValue($testDBO)
242
        );
243
244
        $this->assertFalse($testDBO->isLoaded());
245
    }
246
247
    public function testWakeup()
248
    {
249
        $mock = $this->getMockBuilder(\Suricate\DBObject::class)
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\MockOb...ckBuilder::setMethods() has been deprecated: https://github.com/sebastianbergmann/phpunit/pull/3687 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

249
        $mock = /** @scrutinizer ignore-deprecated */ $this->getMockBuilder(\Suricate\DBObject::class)

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
250
            ->setMethods(['setRelations'])
251
            ->getMock();
252
253
        $mock->expects($this->once())->method('setRelations');
254
255
        $mock->__wakeup();
256
    }
257
258
    public function testRelationOneOne()
259
    {
260
        $relations = [
261
            'category' => [
262
                'type' => \Suricate\DBObject::RELATION_ONE_ONE,
263
                'source' => 'category_id',
264
                'target' => 'Category'
265
            ]
266
        ];
267
        // Prepare database
268
        $this->setupData();
269
        $mock = $this->getMockBuilder(\Suricate\DBObject::class)
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\MockOb...ckBuilder::setMethods() has been deprecated: https://github.com/sebastianbergmann/phpunit/pull/3687 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

269
        $mock = /** @scrutinizer ignore-deprecated */ $this->getMockBuilder(\Suricate\DBObject::class)

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
270
            ->setMethods(['setRelations', 'getRelation'])
271
            ->getMock();
272
273
        // Prepare setup DBObject
274
        $testDBO = $this->getDBOject();
275
        $reflector = new ReflectionClass($mock);
276
        $property = $reflector->getProperty('relations');
277
        $property->setAccessible(true);
278
        $property->setValue($testDBO, $relations);
279
280
        // get relation values
281
        $reflector = new ReflectionClass($testDBO);
282
        $relationValuesRef = $reflector->getProperty('relationValues');
283
        $relationValuesRef->setAccessible(true);
284
285
        $loadedRelationsRef = $reflector->getProperty('loadedRelations');
286
        $loadedRelationsRef->setAccessible(true);
287
288
        // Load
289
        $testDBO->load(1);
290
        $relationsValues = $relationValuesRef->getValue($testDBO);
291
        $loadedRelations = $loadedRelationsRef->getValue($testDBO);
292
293
        // No relation values at first
294
        $this->assertSame([], $relationsValues);
295
        $this->assertSame([], $loadedRelations);
296
        $this->assertEquals('Admin', $testDBO->category->name);
0 ignored issues
show
Bug Best Practice introduced by
The property category does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
297
        $this->assertInstanceOf('\Suricate\DBObject', $testDBO->category);
298
299
        $relationsValues = $relationValuesRef->getValue($testDBO);
300
        $loadedRelations = $loadedRelationsRef->getValue($testDBO);
301
302
        // Check relation cache has been set
303
        $this->assertArrayHasKey('category', $relationsValues);
304
305
        // Check relation loaded flag has been set
306
        $this->assertArrayHasKey('category', $loadedRelations);
307
308
        // Check return type of relation
309
        $this->assertInstanceOf(
310
            '\Suricate\DBObject',
311
            $relationsValues['category']
312
        );
313
314
        // Load new object
315
        $testDBO = $this->getDBOject();
316
        $reflector = new ReflectionClass($mock);
317
        $property = $reflector->getProperty('relations');
318
        $property->setAccessible(true);
319
        $property->setValue($testDBO, $relations);
320
        $testDBO->load(2);
321
        // get relation values
322
        $reflector = new ReflectionClass($testDBO);
323
        $relationValuesRef = $reflector->getProperty('relationValues');
324
        $relationValuesRef->setAccessible(true);
325
326
        $loadedRelationsRef = $reflector->getProperty('loadedRelations');
327
        $loadedRelationsRef->setAccessible(true);
328
329
        $relationsValues = $relationValuesRef->getValue($testDBO);
330
        $loadedRelations = $loadedRelationsRef->getValue($testDBO);
331
332
        // No relation values at first
333
        $this->assertSame([], $relationsValues);
334
        $this->assertSame([], $loadedRelations);
335
336
        // Isset implicit load relation, check that's been loaded
337
        $this->assertTrue(isset($testDBO->category));
338
    }
339
340
    public function testLoad()
341
    {
342
        // Prepare database
343
        $this->setupData();
344
345
        // Inject database handler
346
        $testDBO = $this->getDBOject();
347
348
        $this->assertFalse($testDBO->isLoaded());
349
        $retVal = $testDBO->load(1);
350
        $this->assertTrue($testDBO->isLoaded());
351
        $this->assertEquals(1, $testDBO->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
352
353
        $this->assertEquals('John', $testDBO->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
354
355
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
356
    }
357
358
    public function testSetInsertIgnore()
359
    {
360
        $testDBO = $this->getDBOject();
361
        $reflectionClass = new \ReflectionClass($testDBO);
362
363
        $property = $reflectionClass->getProperty('insertIgnore');
364
        $property->setAccessible(true);
365
366
        $this->assertFalse($property->getValue($testDBO));
367
        $retVal = $testDBO->setInsertIgnore(true);
368
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
369
370
        $this->assertTrue($property->getValue($testDBO));
371
    }
372
373
    public function testSaveUpdate()
374
    {
375
        // Prepare database
376
        $this->setupData();
377
378
        // Simple save
379
        $testDBO = $this->getDBOject();
380
        $testDBO->id = 55;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
381
        $testDBO->name = 'Steve';
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
382
        $testDBO->date_added = '2019-01-27';
0 ignored issues
show
Bug Best Practice introduced by
The property date_added does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
383
        $testDBO->save();
384
385
        $loaded = $this->getDBOject();
386
        $retVal = $loaded->load(55);
387
        $this->assertTrue($testDBO->isLoaded());
388
        $this->assertEquals(55, $loaded->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
389
        $this->assertEquals('Steve', $loaded->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
390
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
391
392
        // Update
393
        $loaded->name = 'Tim';
394
        $loaded->save();
395
        $loaded = $this->getDBOject();
396
        $retVal = $loaded->load(55);
397
        $this->assertTrue($testDBO->isLoaded());
398
        $this->assertEquals(55, $loaded->id);
399
        $this->assertEquals('Tim', $loaded->name);
400
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
401
    }
402
403
    public function testForceInsert()
404
    {
405
        // Prepare database
406
        $this->setupData();
407
408
        // Force insert
409
        $loadedForce = $this->getDBOject();
410
        $retVal = $loadedForce->load(1);
0 ignored issues
show
Unused Code introduced by
The assignment to $retVal is dead and can be removed.
Loading history...
411
        $loadedForce->id = 56;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
412
        $loadedForce->save(true);
413
414
        $loaded = $this->getDBOject();
415
        $retVal = $loaded->load(56);
416
417
        $this->assertEquals(56, $loaded->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
418
        $this->assertEquals('John', $loaded->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
419
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
420
    }
421
422
    public function testDelete()
423
    {
424
        // Prepare database
425
        $this->setupData();
426
427
        // Simple save
428
        $testDBO = $this->getDBOject();
429
        $testDBO->id = 55;
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
430
        $testDBO->name = 'Steve';
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
431
        $testDBO->date_added = '2019-01-27';
0 ignored issues
show
Bug Best Practice introduced by
The property date_added does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
432
        $testDBO->save();
433
434
        $testDBO = $this->getDBOject();
435
        $retVal = $testDBO->loadOrFail(55);
436
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
437
438
        $testDBO->delete();
439
440
        $testDBO = $this->getDBOject();
441
        $this->expectException(
442
            \Suricate\Exception\ModelNotFoundException::class
443
        );
444
        $testDBO->loadOrFail(55);
445
    }
446
447
    public function testLoadFromSQL()
448
    {
449
        // Prepare database
450
        $this->setupData();
451
452
        // Inject database handler
453
        $testDBO = $this->getDBOject();
454
455
        $sql = "SELECT * FROM `users` WHERE id=:id";
456
        $params = ['id' => 1];
457
458
        $retVal = $testDBO->loadFromSql($sql, $params);
459
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
460
        $this->assertTrue($testDBO->isLoaded());
461
462
        $params = ['id' => 100];
463
        $retVal = $testDBO->loadFromSql($sql, $params);
464
        $this->assertFalse($retVal);
465
        $this->assertFalse($testDBO->isLoaded());
466
    }
467
468
    public function testLoadOrFail()
469
    {
470
        // Prepare database
471
        $this->setupData();
472
473
        // Inject database handler
474
        $testDBO = $this->getDBOject();
475
476
        $retVal = $testDBO->loadOrFail(1);
477
        $this->assertInstanceOf('\Suricate\DBObject', $retVal);
478
479
        $this->expectException(
480
            \Suricate\Exception\ModelNotFoundException::class
481
        );
482
        $testDBO->loadOrFail(100);
483
    }
484
485
    public function testLoadOrInstanciate()
486
    {
487
        // Prepare database
488
        $this->setupData();
489
490
        $testDBO = Category::loadOrInstanciate(100);
491
492
        $comparison = $this->getCategoryDBOject();
493
        $comparison->load(100);
494
495
        $this->assertInstanceOf('\Suricate\DBObject', $testDBO);
496
        $this->assertInstanceOf('Category', $testDBO);
497
498
        $this->assertSame($comparison->id, $testDBO->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Category. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
499
        $this->assertSame($comparison->name, $testDBO->name);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property name does not exist on Category. Since you implemented __get, consider adding a @property annotation.
Loading history...
500
        $this->assertTrue($testDBO->isLoaded());
501
502
        // non existing
503
        $testDBO = Category::loadOrInstanciate(102);
504
        $this->assertFalse($testDBO->isLoaded()); // has been instanciated, not loaded
505
        $this->assertSame($testDBO->id, "102");
506
        $this->assertSame($testDBO->name, null);
507
508
        $testDBO = Category::loadOrInstanciate([
509
            'id' => 102,
510
            'name' => 'test name'
511
        ]);
512
        $this->assertFalse($testDBO->isLoaded());
513
        $this->assertSame($testDBO->id, "102");
514
        $this->assertSame($testDBO->name, 'test name');
515
516
        $testDBO = Category::loadOrInstanciate([
517
            'id' => 101,
518
            'name' => 'test name'
519
        ]);
520
        $this->assertFalse($testDBO->isLoaded());
521
        $this->assertSame($testDBO->id, "101");
522
        $this->assertSame($testDBO->name, 'test name');
523
524
        $testDBO = Category::loadOrInstanciate([
525
            'id' => 101,
526
            'name' => 'Employee'
527
        ]);
528
        $this->assertTrue($testDBO->isLoaded());
529
        $this->assertSame($testDBO->id, "101");
530
        $this->assertSame($testDBO->name, 'Employee');
531
    }
532
533
    public function testCreate()
534
    {
535
        // Prepare database
536
        $this->setupData();
537
        $comparison = $this->getCategoryDBOject();
538
539
        $testDBO = Category::create(['id' => 1020]);
540
541
        $this->assertInstanceOf('\Suricate\DBObject', $testDBO);
542
        $this->assertTrue($testDBO->isLoaded());
543
544
        $comparison->load(1020);
545
546
        $this->assertSame($comparison->id, $testDBO->id);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property id does not exist on Category. Since you implemented __get, consider adding a @property annotation.
Loading history...
547
        $this->assertSame($comparison->name, null);
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
548
    }
549
550
    public function testToArray()
551
    {
552
        // Prepare database
553
        $this->setupData();
554
555
        // Inject database handler
556
        $testDBO = $this->getDBOject();
557
        $testDBO->load(2);
558
559
        $this->assertSame(
560
            [
561
                'id' => '2',
562
                'category_id' => '100',
563
                'name' => 'Paul',
564
                'date_added' => '2019-01-11 00:00:00'
565
            ],
566
            $testDBO->toArray()
567
        );
568
569
        $testDBO = $this->getDBOject();
570
        $testDBO->load(2);
571
        self::mockProperty($testDBO, 'exportedVariables', [
572
            'id' => 'id',
573
            'category_id' => 'category_id,type:integer',
574
            'name' => ',omitempty',
575
            'date_added' => '-'
576
        ]);
577
        $testDBO->name = '';
0 ignored issues
show
Bug Best Practice introduced by
The property name does not exist on Suricate\DBObject. Since you implemented __set, consider adding a @property annotation.
Loading history...
578
579
        $this->assertSame(
580
            [
581
                'id' => '2',
582
                'category_id' => 100
583
            ],
584
            $testDBO->toArray()
585
        );
586
    }
587
588
    public function testToJson()
589
    {
590
        // Prepare database
591
        $this->setupData();
592
593
        // Inject database handler
594
        $testDBO = $this->getDBOject();
595
        $testDBO->load(2);
596
597
        $this->assertSame(
598
            '{"id":"2","category_id":"100","name":"Paul","date_added":"2019-01-11 00:00:00"}',
599
            $testDBO->toJson()
600
        );
601
    }
602
603
    public function testValidate()
604
    {
605
        $testDBO = $this->getDBOject();
606
        $this->assertTrue($testDBO->validate());
607
    }
608
609
    public static function mockProperty($object, string $propertyName, $value)
610
    {
611
        $reflectionClass = new \ReflectionClass($object);
612
613
        $property = $reflectionClass->getProperty($propertyName);
614
        $property->setAccessible(true);
615
        $property->setValue($object, $value);
616
        $property->setAccessible(false);
617
    }
618
619
    protected function setupData()
620
    {
621
        $pdo = new PDO('sqlite:/tmp/test.db');
622
        $pdo->exec("DROP TABLE IF EXISTS `users`");
623
        $pdo->exec("DROP TABLE IF EXISTS `categories`");
624
        $pdo->exec(
625
            "CREATE TABLE `users` (`id` INTEGER PRIMARY KEY,`category_id` INTEGER, `name` varchar(50) DEFAULT NULL,`date_added` datetime NOT NULL)"
626
        );
627
        $pdo->exec(
628
            "CREATE TABLE `categories` (`id` INTEGER PRIMARY KEY, `name` varchar(50) DEFAULT NULL, `parent_id` INTEGER DEFAULT NULL)"
629
        );
630
631
        $stmt = $pdo->prepare(
632
            "INSERT INTO `users` (name, category_id, date_added) VALUES (:name, :categoryid, :date)"
633
        );
634
        $values = [
635
            ['John', 100, '2019-01-10 00:00:00'],
636
            ['Paul', 100, '2019-01-11 00:00:00'],
637
            ['Robert', 101, '2019-01-12 00:00:00']
638
        ];
639
        foreach ($values as $value) {
640
            $stmt->execute([
641
                'name' => $value[0],
642
                'categoryid' => $value[1],
643
                'date' => $value[2]
644
            ]);
645
        }
646
647
        $stmt = $pdo->prepare(
648
            "INSERT INTO `categories` (id, name) VALUES (:id, :name)"
649
        );
650
        $values = [[100, 'Admin'], [101, 'Employee']];
651
        foreach ($values as $value) {
652
            $stmt->execute(['id' => $value[0], 'name' => $value[1]]);
653
        }
654
    }
655
656
    protected function getDatabase()
657
    {
658
        $database = new \Suricate\Database();
659
        $database->configure([
660
            'type' => 'sqlite',
661
            'file' => '/tmp/test.db'
662
        ]);
663
664
        return $database;
665
    }
666
667
    protected function getDBOject()
668
    {
669
        $dbLink = $this->getDatabase();
670
        // Inject database handler
671
        $testDBO = new \Suricate\DBObject();
672
673
        $reflector = new ReflectionClass(get_class($testDBO));
674
        $property = $reflector->getProperty('dbLink');
675
        $property->setAccessible(true);
676
        $property->setValue($testDBO, $dbLink);
677
678
        self::mockProperty($testDBO, 'tableName', $this->tableName);
679
        self::mockProperty($testDBO, 'tableIndex', 'id');
680
        self::mockProperty($testDBO, 'dbVariables', [
681
            'id',
682
            'category_id',
683
            'name',
684
            'date_added'
685
        ]);
686
687
        return $testDBO;
688
    }
689
690
    protected function getCategoryDBOject()
691
    {
692
        $dbLink = $this->getDatabase();
693
        // Inject database handler
694
        $testDBO = new \Suricate\DBObject();
695
696
        $reflector = new ReflectionClass(get_class($testDBO));
697
        $property = $reflector->getProperty('dbLink');
698
        $property->setAccessible(true);
699
        $property->setValue($testDBO, $dbLink);
700
701
        self::mockProperty($testDBO, 'tableName', 'categories');
702
        self::mockProperty($testDBO, 'tableIndex', 'id');
703
        self::mockProperty($testDBO, 'dbVariables', ['id', 'name']);
704
705
        return $testDBO;
706
    }
707
}
708