Passed
Branch add-rector-actions (5668b1)
by Wilmer
03:26
created

testRefreshQuerySetAliasFindRecord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 10
rs 10
c 1
b 0
f 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Tests;
6
7
use ReflectionException;
8
use Yiisoft\ActiveRecord\ActiveQuery;
9
use Yiisoft\ActiveRecord\ActiveRecordInterface;
10
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Animal;
11
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat;
12
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
13
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\CustomerWithAlias;
14
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Dog;
15
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Item;
16
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\NoExist;
17
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\NullValues;
18
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Order;
19
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\OrderItem;
20
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Type;
21
use Yiisoft\Db\Exception\Exception;
22
use Yiisoft\Db\Exception\InvalidArgumentException;
23
use Yiisoft\Db\Exception\InvalidCallException;
24
use Yiisoft\Db\Exception\InvalidConfigException;
25
use Yiisoft\Db\Query\Query;
26
27
abstract class ActiveRecordTest extends TestCase
28
{
29
    public function testStoreNull(): void
30
    {
31
        $this->checkFixture($this->db, 'null_values', true);
32
33
        $record = new NullValues($this->db);
34
35
        $this->assertNull($record->getAttribute('var1'));
36
        $this->assertNull($record->getAttribute('var2'));
37
        $this->assertNull($record->getAttribute('var3'));
38
        $this->assertNull($record->getAttribute('stringcol'));
39
40
        $record->setAttribute('var1', 123);
41
        $record->setAttribute('var2', 456);
42
        $record->setAttribute('var3', 789);
43
        $record->setAttribute('stringcol', 'hello!');
44
        $record->save();
45
46
        $this->assertTrue($record->refresh());
47
        $this->assertEquals(123, $record->getAttribute('var1'));
48
        $this->assertEquals(456, $record->getAttribute('var2'));
49
        $this->assertEquals(789, $record->getAttribute('var3'));
50
        $this->assertEquals('hello!', $record->getAttribute('stringcol'));
51
52
        $record->setAttribute('var1', null);
53
        $record->setAttribute('var2', null);
54
        $record->setAttribute('var3', null);
55
        $record->setAttribute('stringcol', null);
56
        $record->save();
57
58
        $this->assertTrue($record->refresh());
59
        $this->assertNull($record->getAttribute('var1'));
60
        $this->assertNull($record->getAttribute('var2'));
61
        $this->assertNull($record->getAttribute('var3'));
62
        $this->assertNull($record->getAttribute('>stringcol'));
63
64
        $record->setAttribute('var1', 0);
65
        $record->setAttribute('var2', 0);
66
        $record->setAttribute('var3', 0);
67
        $record->setAttribute('stringcol', '');
68
        $record->save();
69
70
        $this->assertTrue($record->refresh());
71
        $this->assertEquals(0, $record->getAttribute('var1'));
72
        $this->assertEquals(0, $record->getAttribute('var2'));
73
        $this->assertEquals(0, $record->getAttribute('var3'));
74
        $this->assertEquals('', $record->getAttribute('stringcol'));
75
    }
76
77
    public function testStoreEmpty(): void
78
    {
79
        $this->checkFixture($this->db, 'null_values');
80
81
        $record = new NullValues($this->db);
82
83
        /** this is to simulate empty html form submission */
84
        $record->var1 = '';
0 ignored issues
show
Documentation Bug introduced by
The property $var1 was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
85
        $record->var2 = '';
0 ignored issues
show
Documentation Bug introduced by
The property $var2 was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
86
        $record->var3 = '';
0 ignored issues
show
Documentation Bug introduced by
The property $var3 was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
87
        $record->stringcol = '';
88
        $record->save();
89
90
        $this->assertTrue($record->refresh());
91
92
        /** {@see https://github.com/yiisoft/yii2/commit/34945b0b69011bc7cab684c7f7095d837892a0d4#commitcomment-4458225} */
93
        $this->assertSame($record->var1, $record->var2);
94
        $this->assertSame($record->var2, $record->var3);
95
    }
96
97
    public function testIsPrimaryKey(): void
98
    {
99
        $this->checkFixture($this->db, 'customer');
100
101
        $customer = new Customer($this->db);
102
        $orderItem = new OrderItem($this->db);
103
104
        $this->assertTrue($customer->isPrimaryKey(['id']));
105
        $this->assertFalse($customer->isPrimaryKey([]));
106
        $this->assertFalse($customer->isPrimaryKey(['id', 'name']));
107
        $this->assertFalse($customer->isPrimaryKey(['name']));
108
        $this->assertFalse($customer->isPrimaryKey(['name', 'email']));
109
110
        $this->assertTrue($orderItem->isPrimaryKey(['order_id', 'item_id']));
111
        $this->assertFalse($orderItem->isPrimaryKey([]));
112
        $this->assertFalse($orderItem->isPrimaryKey(['order_id']));
113
        $this->assertFalse($orderItem->isPrimaryKey(['item_id']));
114
        $this->assertFalse($orderItem->isPrimaryKey(['quantity']));
115
        $this->assertFalse($orderItem->isPrimaryKey(['quantity', 'subtotal']));
116
        $this->assertFalse($orderItem->isPrimaryKey(['order_id', 'item_id', 'quantity']));
117
    }
118
119
    public function testOutdatedRelationsAreResetForNewRecords(): void
120
    {
121
        $this->checkFixture($this->db, 'order_item');
122
123
        $orderItem = new OrderItem($this->db);
124
125
        $orderItem->order_id = 1;
126
        $orderItem->item_id = 3;
127
        $this->assertEquals(1, $orderItem->order->id);
0 ignored issues
show
Bug Best Practice introduced by
The property order does not exist on Yiisoft\ActiveRecord\Tes...\ActiveRecord\OrderItem. Since you implemented __get, consider adding a @property annotation.
Loading history...
128
        $this->assertEquals(3, $orderItem->item->id);
0 ignored issues
show
Bug Best Practice introduced by
The property item does not exist on Yiisoft\ActiveRecord\Tes...\ActiveRecord\OrderItem. Since you implemented __get, consider adding a @property annotation.
Loading history...
129
130
        /** test `__set()`. */
131
        $orderItem->order_id = 2;
132
        $orderItem->item_id = 1;
133
        $this->assertEquals(2, $orderItem->order->id);
134
        $this->assertEquals(1, $orderItem->item->id);
135
136
        /** test `setAttribute()`. */
137
        $orderItem->setAttribute('order_id', 2);
138
        $orderItem->setAttribute('item_id', 2);
139
        $this->assertEquals(2, $orderItem->order->id);
140
        $this->assertEquals(2, $orderItem->item->id);
141
    }
142
143
    public function testDefaultValues(): void
144
    {
145
        $this->checkFixture($this->db, 'type');
146
147
        $arClass = new Type($this->db);
148
149
        $arClass->loadDefaultValues();
150
151
        $this->assertEquals(1, $arClass->int_col2);
152
        $this->assertEquals('something', $arClass->char_col2);
153
        $this->assertEquals(1.23, $arClass->float_col2);
154
        $this->assertEquals(33.22, $arClass->numeric_col);
155
        $this->assertEquals(true, $arClass->bool_col2);
156
        $this->assertEquals('2002-01-01 00:00:00', $arClass->time);
157
158
        $arClass = new Type($this->db);
159
        $arClass->char_col2 = 'not something';
160
161
        $arClass->loadDefaultValues();
162
        $this->assertEquals('not something', $arClass->char_col2);
163
164
        $arClass = new Type($this->db);
165
        $arClass->char_col2 = 'not something';
166
167
        $arClass->loadDefaultValues(false);
168
        $this->assertEquals('something', $arClass->char_col2);
169
    }
170
171
    public function testCastValues(): void
172
    {
173
        $this->checkFixture($this->db, 'type');
174
175
        $arClass = new Type($this->db);
176
177
        $arClass->int_col = 123;
178
        $arClass->int_col2 = 456;
179
        $arClass->smallint_col = 42;
180
        $arClass->char_col = '1337';
181
        $arClass->char_col2 = 'test';
182
        $arClass->char_col3 = 'test123';
183
        $arClass->float_col = 3.742;
184
        $arClass->float_col2 = 42.1337;
185
        $arClass->bool_col = true;
186
        $arClass->bool_col2 = false;
187
188
        $arClass->save();
189
190
        /** @var $model Type */
191
        $aqClass = new ActiveQuery(Type::class, $this->db);
192
        $query = $aqClass->one();
193
194
        $this->assertSame(123, $query->int_col);
195
        $this->assertSame(456, $query->int_col2);
196
        $this->assertSame(42, $query->smallint_col);
197
        $this->assertSame('1337', trim($query->char_col));
198
        $this->assertSame('test', $query->char_col2);
199
        $this->assertSame('test123', $query->char_col3);
200
    }
201
202
    public function testPopulateRecordCallWhenQueryingOnParentClass(): void
203
    {
204
        $this->checkFixture($this->db, 'cat');
205
206
        $cat = new Cat($this->db);
207
        $cat->save();
208
209
        $dog = new Dog($this->db);
210
        $dog->save();
211
212
        $animal = new ActiveQuery(Animal::class, $this->db);
213
214
        $animals = $animal->where(['type' => Dog::class])->one();
215
        $this->assertEquals('bark', $animals->getDoes());
216
217
        $animals = $animal->where(['type' => Cat::class])->one();
218
        $this->assertEquals('meow', $animals->getDoes());
219
    }
220
221
    public function testSaveEmpty(): void
222
    {
223
        $this->checkFixture($this->db, 'null_values');
224
225
        $this->loadFixture($this->db);
226
227
        $record = new NullValues($this->db);
228
229
        $this->assertTrue($record->save());
230
        $this->assertEquals(1, $record->id);
231
    }
232
233
    /**
234
     * Verify that {{}} are not going to be replaced in parameters.
235
     */
236
    public function testNoTablenameReplacement(): void
237
    {
238
        $this->checkFixture($this->db, 'customer');
239
240
        $customer = new Customer($this->db);
241
242
        $customer->name = 'Some {{weird}} name';
243
        $customer->email = '[email protected]';
244
        $customer->address = 'Some {{%weird}} address';
245
        $customer->insert();
246
        $customer->refresh();
247
248
        $this->assertEquals('Some {{weird}} name', $customer->name);
249
        $this->assertEquals('Some {{%weird}} address', $customer->address);
250
251
        $customer->name = 'Some {{updated}} name';
252
        $customer->address = 'Some {{%updated}} address';
253
        $customer->update();
254
255
        $this->assertEquals('Some {{updated}} name', $customer->name);
256
        $this->assertEquals('Some {{%updated}} address', $customer->address);
257
    }
258
259
    public function legalValuesForFindByCondition(): array
260
    {
261
        return [
262
            [Customer::class, ['id' => 1]],
263
            [Customer::class, ['customer.id' => 1]],
264
            [Customer::class, ['[[id]]' => 1]],
265
            [Customer::class, ['{{customer}}.[[id]]' => 1]],
266
            [Customer::class, ['{{%customer}}.[[id]]' => 1]],
267
            [CustomerWithAlias::class, ['id' => 1]],
268
            [CustomerWithAlias::class, ['customer.id' => 1]],
269
            [CustomerWithAlias::class, ['[[id]]' => 1]],
270
            [CustomerWithAlias::class, ['{{customer}}.[[id]]' => 1]],
271
            [CustomerWithAlias::class, ['{{%customer}}.[[id]]' => 1]],
272
            [CustomerWithAlias::class, ['csr.id' => 1], 'csr'],
273
            [CustomerWithAlias::class, ['{{csr}}.[[id]]' => 1], 'csr'],
274
        ];
275
    }
276
277
    /**
278
     * @dataProvider legalValuesForFindByCondition
279
     *
280
     * @throws ReflectionException
281
     */
282
    public function testLegalValuesForFindByCondition(
283
        string $modelClassName,
284
        array $validFilter,
285
        ?string $alias = null
286
    ): void {
287
        $this->checkFixture($this->db, 'customer');
288
289
        $activeQuery = new ActiveQuery($modelClassName, $this->db);
290
291
        if ($alias !== null) {
292
            $activeQuery->alias('csr');
293
        }
294
295
        /** @var Query $query */
296
        $query = $this->invokeMethod($activeQuery, 'findByCondition', [$validFilter]);
297
298
299
        $this->db->getQueryBuilder()->build($query);
300
301
        $this->assertTrue(true);
302
    }
303
304
    public function illegalValuesForFindByCondition(): array
305
    {
306
        return [
307
            [Customer::class, [['`id`=`id` and 1' => 1]]],
308
            [Customer::class, [[
309
                'legal' => 1,
310
                '`id`=`id` and 1' => 1,
311
            ]]],
312
            [Customer::class, [[
313
                'nested_illegal' => [
314
                    'false or 1=' => 1,
315
                ],
316
            ]]],
317
            [Customer::class, [['true--' => 1]]],
318
319
            [CustomerWithAlias::class, [['`csr`.`id`=`csr`.`id` and 1' => 1]]],
320
            [CustomerWithAlias::class, [[
321
                'legal' => 1,
322
                '`csr`.`id`=`csr`.`id` and 1' => 1,
323
            ]]],
324
            [CustomerWithAlias::class, [[
325
                'nested_illegal' => [
326
                    'false or 1=' => 1,
327
                ],
328
            ]]],
329
            [CustomerWithAlias::class, [['true--' => 1]]],
330
        ];
331
    }
332
333
    /**
334
     * @dataProvider illegalValuesForFindByCondition
335
     *
336
     * @throws ReflectionException
337
     */
338
    public function testValueEscapingInFindByCondition(string $modelClassName, array $filterWithInjection): void
339
    {
340
        $this->checkFixture($this->db, 'customer');
341
        $this->expectException(InvalidArgumentException::class);
342
        $this->expectExceptionMessageMatches(
343
            '/^Key "(.+)?" is not a column name and can not be used as a filter$/'
344
        );
345
346
        $query = new ActiveQuery($modelClassName, $this->db);
347
348
        /** @var Query $query */
349
        $query = $this->invokeMethod(
350
            $query,
351
            'findByCondition',
352
            $filterWithInjection
353
        );
354
355
        $this->db->getQueryBuilder()->build($query);
356
    }
357
358
    public function testRefreshQuerySetAliasFindRecord(): void
359
    {
360
        $this->checkFixture($this->db, 'customer');
361
362
        $customer = new CustomerWithAlias($this->db);
363
364
        $customer->id = 1;
365
        $customer->refresh();
366
367
        $this->assertEquals(1, $customer->id);
368
    }
369
370
    public function testResetNotSavedRelation(): void
371
    {
372
        $this->checkFixture($this->db, 'order');
373
374
        $order = new Order($this->db);
375
376
        $order->customer_id = 1;
377
        $order->created_at = 1_325_502_201;
0 ignored issues
show
Bug introduced by
The constant Yiisoft\ActiveRecord\Tests\1_325_502_201 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
378
        $order->total = 0;
379
380
        $orderItem = new OrderItem($this->db);
381
382
        $order->orderItems;
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\Tes...tubs\ActiveRecord\Order. Since you implemented __get, consider adding a @property annotation.
Loading history...
383
384
        $order->populateRelation('orderItems', [$orderItem]);
385
386
        $order->save();
387
388
        $this->assertCount(1, $order->orderItems);
389
    }
390
391
    public function testIssetException(): void
392
    {
393
        $this->checkFixture($this->db, 'cat');
394
395
        $cat = new Cat($this->db);
396
397
        $this->assertFalse(isset($cat->exception));
0 ignored issues
show
Bug Best Practice introduced by
The property exception does not exist on Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat. Since you implemented __get, consider adding a @property annotation.
Loading history...
398
    }
399
400
    public function testIssetThrowable(): void
401
    {
402
        $this->checkFixture($this->db, 'cat');
403
404
        $cat = new Cat($this->db);
405
406
        $this->assertFalse(isset($cat->throwable));
0 ignored issues
show
Bug Best Practice introduced by
The property throwable does not exist on Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat. Since you implemented __get, consider adding a @property annotation.
Loading history...
407
    }
408
409
    public function testSetAttributes(): void
410
    {
411
        $attributes = [];
412
        $this->checkFixture($this->db, 'customer');
413
414
        $attributes['email'] = '[email protected]';
415
        $attributes['name'] = 'samdark';
416
        $attributes['address'] = 'rusia';
417
        $attributes['status'] = 1;
418
419
        if ($this->driverName === 'pgsql') {
420
            $attributes['bool_status'] = true;
421
        }
422
423
        $attributes['profile_id'] = null;
424
425
        $customer = new Customer($this->db);
426
427
        $customer->setAttributes($attributes);
428
429
        $this->assertTrue($customer->save());
430
    }
431
432
    public function testSetAttributeNoExist(): void
433
    {
434
        $this->checkFixture($this->db, 'cat');
435
436
        $cat = new Cat($this->db);
437
438
        $this->expectException(InvalidArgumentException::class);
439
        $this->expectExceptionMessage(
440
            'Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Cat has no attribute named "noExist"'
441
        );
442
443
        $cat->setAttribute('noExist', 1);
444
    }
445
446
    public function testSetOldAttribute(): void
447
    {
448
        $this->checkFixture($this->db, 'customer');
449
450
        $customer = new Customer($this->db);
451
452
        $this->assertEmpty($customer->getOldAttribute('name'));
453
454
        $customer->setOldAttribute('name', 'samdark');
455
456
        $this->assertEquals('samdark', $customer->getOldAttribute('name'));
457
    }
458
459
    public function testSetOldAttributeException(): void
460
    {
461
        $this->checkFixture($this->db, 'customer');
462
463
        $customer = new Customer($this->db);
464
465
        $this->assertEmpty($customer->getOldAttribute('name'));
466
467
        $this->expectException(InvalidArgumentException::class);
468
        $this->expectExceptionMessage(
469
            'Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer has no attribute named "noExist"'
470
        );
471
        $customer->setOldAttribute('noExist', 'samdark');
472
    }
473
474
    public function testIsAttributeChangedNotChanged(): void
475
    {
476
        $this->checkFixture($this->db, 'customer');
477
478
        $customer = new Customer($this->db);
479
480
        $this->assertEmpty($customer->getAttribute('name'));
481
        $this->assertEmpty($customer->getOldAttribute('name'));
482
        $this->assertFalse($customer->isAttributeChanged('name', false));
483
    }
484
485
    public function testTableSchemaException(): void
486
    {
487
        $noExist = new NoExist($this->db);
488
489
        $this->expectException(InvalidConfigException::class);
490
        $this->expectExceptionMessage('The table does not exist: NoExist');
491
        $noExist->getTableSchema();
492
    }
493
494
    public function testInsert(): void
495
    {
496
        $this->checkFixture($this->db, 'customer');
497
498
        $customer = new Customer($this->db);
499
500
        $customer->email = '[email protected]';
501
        $customer->name = 'user4';
502
        $customer->address = 'address4';
503
504
        $this->assertNull($customer->id);
505
        $this->assertTrue($customer->isNewRecord);
506
507
        $customer->save();
508
509
        $this->assertNotNull($customer->id);
510
        $this->assertFalse($customer->isNewRecord);
511
    }
512
513
    /**
514
     * Some PDO implementations (e.g. cubrid) do not support boolean values.
515
     *
516
     * Make sure this does not affect AR layer.
517
     */
518
    public function testBooleanAttribute(): void
519
    {
520
        $this->checkFixture($this->db, 'customer');
521
522
        $this->loadFixture($this->db);
523
524
        $customer = new Customer($this->db);
525
526
        $customer->name = 'boolean customer';
527
        $customer->email = '[email protected]';
528
        $customer->status = true;
0 ignored issues
show
Documentation Bug introduced by
The property $status was declared of type integer, but true is of type true. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
529
530
        $customer->save();
531
        $customer->refresh();
532
        $this->assertEquals(1, $customer->status);
533
534
        $customer->status = false;
535
        $customer->save();
536
537
        $customer->refresh();
538
        $this->assertEquals(0, $customer->status);
539
540
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
541
        $customers = $customerQuery->where(['status' => true])->all();
542
        $this->assertCount(2, $customers);
543
544
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
545
        $customers = $customerQuery->where(['status' => false])->all();
546
        $this->assertCount(1, $customers);
547
    }
548
549
    public function testAttributeAccess(): void
550
    {
551
        $this->checkFixture($this->db, 'customer');
552
553
        $arClass = new Customer($this->db);
554
555
        $this->assertTrue($arClass->canSetProperty('name'));
556
        $this->assertTrue($arClass->canGetProperty('name'));
557
        $this->assertFalse($arClass->canSetProperty('unExistingColumn'));
558
        $this->assertFalse(isset($arClass->name));
559
560
        $arClass->name = 'foo';
561
        $this->assertTrue(isset($arClass->name));
562
563
        unset($arClass->name);
564
        $this->assertNull($arClass->name);
565
566
        /** {@see https://github.com/yiisoft/yii2-gii/issues/190} */
567
        $baseModel = new Customer($this->db);
568
        $this->assertFalse($baseModel->hasProperty('unExistingColumn'));
569
570
        $customer = new Customer($this->db);
571
        $this->assertInstanceOf(Customer::class, $customer);
572
        $this->assertTrue($customer->canGetProperty('id'));
573
        $this->assertTrue($customer->canSetProperty('id'));
574
575
        /** tests that we really can get and set this property */
576
        $this->assertNull($customer->id);
577
        $customer->id = 10;
578
        $this->assertNotNull($customer->id);
579
580
        /** Let's test relations */
581
        $this->assertTrue($customer->canGetProperty('orderItems'));
582
        $this->assertFalse($customer->canSetProperty('orderItems'));
583
584
        /** Newly created model must have empty relation */
585
        $this->assertSame([], $customer->orderItems);
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Customer. Since you implemented __get, consider adding a @property annotation.
Loading history...
586
587
        /** does it still work after accessing the relation? */
588
        $this->assertTrue($customer->canGetProperty('orderItems'));
589
        $this->assertFalse($customer->canSetProperty('orderItems'));
590
591
        try {
592
            /** @var $itemClass ActiveRecordInterface */
593
            $customer->orderItems = [new Item($this->db)];
0 ignored issues
show
Bug Best Practice introduced by
The property orderItems does not exist on Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Customer. Since you implemented __set, consider adding a @property annotation.
Loading history...
594
            $this->fail('setter call above MUST throw Exception');
595
        } catch (Exception $e) {
596
            /** catch exception "Setting read-only property" */
597
            $this->assertInstanceOf(InvalidCallException::class, $e);
598
        }
599
600
        /** related attribute $customer->orderItems didn't change cause it's read-only */
601
        $this->assertSame([], $customer->orderItems);
602
        $this->assertFalse($customer->canGetProperty('non_existing_property'));
603
        $this->assertFalse($customer->canSetProperty('non_existing_property'));
604
    }
605
606
    public function testHasAttribute(): void
607
    {
608
        $this->checkFixture($this->db, 'customer');
609
610
        $customer = new Customer($this->db);
611
612
        $this->assertTrue($customer->hasAttribute('id'));
613
        $this->assertTrue($customer->hasAttribute('email'));
614
        $this->assertFalse($customer->hasAttribute(0));
615
        $this->assertFalse($customer->hasAttribute(null));
616
        $this->assertFalse($customer->hasAttribute(42));
617
618
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
619
        $customer = $customerQuery->findOne(1);
620
        $this->assertTrue($customer->hasAttribute('id'));
621
        $this->assertTrue($customer->hasAttribute('email'));
622
        $this->assertFalse($customer->hasAttribute(0));
623
        $this->assertFalse($customer->hasAttribute(null));
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type string expected by parameter $name of Yiisoft\ActiveRecord\Act...terface::hasAttribute(). ( Ignorable by Annotation )

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

623
        $this->assertFalse($customer->hasAttribute(/** @scrutinizer ignore-type */ null));
Loading history...
624
        $this->assertFalse($customer->hasAttribute(42));
625
    }
626
627
    public function testRefresh(): void
628
    {
629
        $this->checkFixture($this->db, 'customer');
630
631
        $customer = new Customer($this->db);
632
633
        $this->assertFalse($customer->refresh());
634
635
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
636
        $customer = $customerQuery->findOne(1);
637
        $customer->name = 'to be refreshed';
0 ignored issues
show
Bug introduced by
Accessing name on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
638
639
        $this->assertTrue($customer->refresh());
0 ignored issues
show
Bug introduced by
The method refresh() does not exist on Yiisoft\ActiveRecord\ActiveRecordInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\ActiveRecord\ActiveRecordInterface. ( Ignorable by Annotation )

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

639
        $this->assertTrue($customer->/** @scrutinizer ignore-call */ refresh());
Loading history...
640
        $this->assertEquals('user1', $customer->name);
641
    }
642
643
    public function testEquals(): void
644
    {
645
        $this->checkFixture($this->db, 'customer');
646
647
        $customerA = new Customer($this->db);
648
        $customerB = new Customer($this->db);
649
        $this->assertFalse($customerA->equals($customerB));
650
651
        $customerA = new Customer($this->db);
652
        $customerB = new Item($this->db);
653
        $this->assertFalse($customerA->equals($customerB));
654
    }
655
}
656