EmbeddedRelationsTest.php 34.7 KB
Newer Older
1
<?php
Simon Schaufelberger's avatar
Simon Schaufelberger committed
2
declare(strict_types=1);
3

Jens Segers's avatar
Jens Segers committed
4 5 6 7
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Events\Dispatcher;
use MongoDB\BSON\ObjectId;

Jens Segers's avatar
Jens Segers committed
8 9
class EmbeddedRelationsTest extends TestCase
{
Stas's avatar
Stas committed
10
    public function tearDown(): void
11 12 13 14 15 16 17 18 19 20 21 22 23 24
    {
        Mockery::close();

        User::truncate();
        Book::truncate();
        Item::truncate();
        Role::truncate();
        Client::truncate();
        Group::truncate();
        Photo::truncate();
    }

    public function testEmbedsManySave()
    {
25 26
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'London']);
27

Jens Segers's avatar
Jens Segers committed
28
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
29
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
30 31 32 33 34 35 36 37
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($address), $address)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.creating: ' . get_class($address), $address)
            ->andReturn(true);
Stas's avatar
Stas committed
38 39
        $events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($address), $address);
        $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
40

41
        $address = $user->addresses()->save($address);
42
        $address->unsetEventDispatcher();
43

44
        $this->assertNotNull($user->addresses);
Divine's avatar
Divine committed
45
        $this->assertInstanceOf(Collection::class, $user->addresses);
Pooya Parsa's avatar
Pooya Parsa committed
46
        $this->assertEquals(['London'], $user->addresses->pluck('city')->all());
Jens Segers's avatar
Jens Segers committed
47 48
        $this->assertInstanceOf(DateTime::class, $address->created_at);
        $this->assertInstanceOf(DateTime::class, $address->updated_at);
49
        $this->assertNotNull($address->_id);
50
        $this->assertIsString($address->_id);
51 52

        $raw = $address->getAttributes();
Jens Segers's avatar
Jens Segers committed
53
        $this->assertInstanceOf(ObjectId::class, $raw['_id']);
54

55
        $address = $user->addresses()->save(new Address(['city' => 'Paris']));
56 57

        $user = User::find($user->_id);
Pooya Parsa's avatar
Pooya Parsa committed
58
        $this->assertEquals(['London', 'Paris'], $user->addresses->pluck('city')->all());
59

Jens Segers's avatar
Jens Segers committed
60
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
61
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
62 63 64 65 66 67 68 69
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($address), $address)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.updating: ' . get_class($address), $address)
            ->andReturn(true);
Stas's avatar
Stas committed
70 71
        $events->shouldReceive('dispatch')->once()->with('eloquent.updated: ' . get_class($address), $address);
        $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
72

73 74
        $address->city = 'New York';
        $user->addresses()->save($address);
75
        $address->unsetEventDispatcher();
76

Gabriel Caruso's avatar
Gabriel Caruso committed
77 78
        $this->assertCount(2, $user->addresses);
        $this->assertCount(2, $user->addresses()->get());
79 80
        $this->assertEquals(2, $user->addresses->count());
        $this->assertEquals(2, $user->addresses()->count());
Pooya Parsa's avatar
Pooya Parsa committed
81
        $this->assertEquals(['London', 'New York'], $user->addresses->pluck('city')->all());
82 83

        $freshUser = User::find($user->_id);
Pooya Parsa's avatar
Pooya Parsa committed
84
        $this->assertEquals(['London', 'New York'], $freshUser->addresses->pluck('city')->all());
85 86 87

        $address = $user->addresses->first();
        $this->assertEquals('London', $address->city);
Jens Segers's avatar
Jens Segers committed
88 89 90
        $this->assertInstanceOf(DateTime::class, $address->created_at);
        $this->assertInstanceOf(DateTime::class, $address->updated_at);
        $this->assertInstanceOf(User::class, $address->user);
91 92 93
        $this->assertEmpty($address->relationsToArray()); // prevent infinite loop

        $user = User::find($user->_id);
94
        $user->addresses()->save(new Address(['city' => 'Bruxelles']));
Pooya Parsa's avatar
Pooya Parsa committed
95
        $this->assertEquals(['London', 'New York', 'Bruxelles'], $user->addresses->pluck('city')->all());
96

97 98 99
        $address = $user->addresses[1];
        $address->city = "Manhattan";
        $user->addresses()->save($address);
Pooya Parsa's avatar
Pooya Parsa committed
100
        $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $user->addresses->pluck('city')->all());
101 102

        $freshUser = User::find($user->_id);
Pooya Parsa's avatar
Pooya Parsa committed
103
        $this->assertEquals(['London', 'Manhattan', 'Bruxelles'], $freshUser->addresses->pluck('city')->all());
104 105
    }

106 107
    public function testEmbedsToArray()
    {
108 109
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol'])]);
110 111

        $array = $user->toArray();
Gabriel Caruso's avatar
Gabriel Caruso committed
112 113
        $this->assertArrayNotHasKey('_addresses', $array);
        $this->assertArrayHasKey('addresses', $array);
114 115
    }

116 117
    public function testEmbedsManyAssociate()
    {
118 119
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'London']);
120

121
        $user->addresses()->associate($address);
Pooya Parsa's avatar
Pooya Parsa committed
122
        $this->assertEquals(['London'], $user->addresses->pluck('city')->all());
123 124 125
        $this->assertNotNull($address->_id);

        $freshUser = User::find($user->_id);
Pooya Parsa's avatar
Pooya Parsa committed
126
        $this->assertEquals([], $freshUser->addresses->pluck('city')->all());
127 128 129

        $address->city = 'Londinium';
        $user->addresses()->associate($address);
Pooya Parsa's avatar
Pooya Parsa committed
130
        $this->assertEquals(['Londinium'], $user->addresses->pluck('city')->all());
131 132

        $freshUser = User::find($user->_id);
Pooya Parsa's avatar
Pooya Parsa committed
133
        $this->assertEquals([], $freshUser->addresses->pluck('city')->all());
134 135 136 137
    }

    public function testEmbedsManySaveMany()
    {
138 139
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol'])]);
Pooya Parsa's avatar
Pooya Parsa committed
140
        $this->assertEquals(['London', 'Bristol'], $user->addresses->pluck('city')->all());
141 142

        $freshUser = User::find($user->id);
Pooya Parsa's avatar
Pooya Parsa committed
143
        $this->assertEquals(['London', 'Bristol'], $freshUser->addresses->pluck('city')->all());
144 145 146 147
    }

    public function testEmbedsManyDuplicate()
    {
148 149
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'London']);
150 151 152
        $user->addresses()->save($address);
        $user->addresses()->save($address);
        $this->assertEquals(1, $user->addresses->count());
Pooya Parsa's avatar
Pooya Parsa committed
153
        $this->assertEquals(['London'], $user->addresses->pluck('city')->all());
154 155 156 157 158 159 160

        $user = User::find($user->id);
        $this->assertEquals(1, $user->addresses->count());

        $address->city = 'Paris';
        $user->addresses()->save($address);
        $this->assertEquals(1, $user->addresses->count());
Pooya Parsa's avatar
Pooya Parsa committed
161
        $this->assertEquals(['Paris'], $user->addresses->pluck('city')->all());
162

163
        $user->addresses()->create(['_id' => $address->_id, 'city' => 'Bruxelles']);
164
        $this->assertEquals(1, $user->addresses->count());
Pooya Parsa's avatar
Pooya Parsa committed
165
        $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all());
166 167 168 169
    }

    public function testEmbedsManyCreate()
    {
170 171
        $user = User::create([]);
        $address = $user->addresses()->create(['city' => 'Bruxelles']);
Jens Segers's avatar
Jens Segers committed
172
        $this->assertInstanceOf(Address::class, $address);
173
        $this->assertIsString($address->_id);
Pooya Parsa's avatar
Pooya Parsa committed
174
        $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all());
175 176

        $raw = $address->getAttributes();
Jens Segers's avatar
Jens Segers committed
177
        $this->assertInstanceOf(ObjectId::class, $raw['_id']);
178 179

        $freshUser = User::find($user->id);
Pooya Parsa's avatar
Pooya Parsa committed
180
        $this->assertEquals(['Bruxelles'], $freshUser->addresses->pluck('city')->all());
181

182 183
        $user = User::create([]);
        $address = $user->addresses()->create(['_id' => '', 'city' => 'Bruxelles']);
184
        $this->assertIsString($address->_id);
185 186

        $raw = $address->getAttributes();
Jens Segers's avatar
Jens Segers committed
187
        $this->assertInstanceOf(ObjectId::class, $raw['_id']);
188 189 190 191
    }

    public function testEmbedsManyCreateMany()
    {
192 193
        $user = User::create([]);
        list($bruxelles, $paris) = $user->addresses()->createMany([['city' => 'Bruxelles'], ['city' => 'Paris']]);
Jens Segers's avatar
Jens Segers committed
194
        $this->assertInstanceOf(Address::class, $bruxelles);
195
        $this->assertEquals('Bruxelles', $bruxelles->city);
Pooya Parsa's avatar
Pooya Parsa committed
196
        $this->assertEquals(['Bruxelles', 'Paris'], $user->addresses->pluck('city')->all());
197 198

        $freshUser = User::find($user->id);
Pooya Parsa's avatar
Pooya Parsa committed
199
        $this->assertEquals(['Bruxelles', 'Paris'], $freshUser->addresses->pluck('city')->all());
200 201
    }

Jens Segers's avatar
Jens Segers committed
202
    public function testEmbedsManyDestroy()
203
    {
204
        $user = User::create(['name' => 'John Doe']);
Jens Segers's avatar
Jens Segers committed
205 206 207 208 209
        $user->addresses()->saveMany([
            new Address(['city' => 'London']),
            new Address(['city' => 'Bristol']),
            new Address(['city' => 'Bruxelles']),
        ]);
210 211 212

        $address = $user->addresses->first();

Jens Segers's avatar
Jens Segers committed
213
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
214
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
215 216 217 218 219 220 221
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.deleting: ' . get_class($address), Mockery::type(Address::class))
            ->andReturn(true);
        $events->shouldReceive('dispatch')
            ->once()
            ->with('eloquent.deleted: ' . get_class($address), Mockery::type(Address::class));
222

223
        $user->addresses()->destroy($address->_id);
Pooya Parsa's avatar
Pooya Parsa committed
224
        $this->assertEquals(['Bristol', 'Bruxelles'], $user->addresses->pluck('city')->all());
225

226 227
        $address->unsetEventDispatcher();

228 229
        $address = $user->addresses->first();
        $user->addresses()->destroy($address);
Pooya Parsa's avatar
Pooya Parsa committed
230
        $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all());
231

232 233
        $user->addresses()->create(['city' => 'Paris']);
        $user->addresses()->create(['city' => 'San Francisco']);
234 235

        $freshUser = User::find($user->id);
Pooya Parsa's avatar
Pooya Parsa committed
236
        $this->assertEquals(['Bruxelles', 'Paris', 'San Francisco'], $freshUser->addresses->pluck('city')->all());
237

Pooya Parsa's avatar
Pooya Parsa committed
238
        $ids = $user->addresses->pluck('_id');
239
        $user->addresses()->destroy($ids);
Pooya Parsa's avatar
Pooya Parsa committed
240
        $this->assertEquals([], $user->addresses->pluck('city')->all());
241 242

        $freshUser = User::find($user->id);
Pooya Parsa's avatar
Pooya Parsa committed
243
        $this->assertEquals([], $freshUser->addresses->pluck('city')->all());
244

Jens Segers's avatar
Jens Segers committed
245 246 247 248 249
        list($london, $bristol, $bruxelles) = $user->addresses()->saveMany([
            new Address(['city' => 'London']),
            new Address(['city' => 'Bristol']),
            new Address(['city' => 'Bruxelles']),
        ]);
250
        $user->addresses()->destroy([$london, $bruxelles]);
Pooya Parsa's avatar
Pooya Parsa committed
251
        $this->assertEquals(['Bristol'], $user->addresses->pluck('city')->all());
Jens Segers's avatar
Jens Segers committed
252
    }
253

254 255
    public function testEmbedsManyDelete()
    {
256
        $user = User::create(['name' => 'John Doe']);
Jens Segers's avatar
Jens Segers committed
257 258 259 260 261
        $user->addresses()->saveMany([
            new Address(['city' => 'London']),
            new Address(['city' => 'Bristol']),
            new Address(['city' => 'Bruxelles']),
        ]);
262 263 264

        $address = $user->addresses->first();

Jens Segers's avatar
Jens Segers committed
265
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
266
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
267 268 269 270 271 272 273
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.deleting: ' . get_class($address), Mockery::type(Address::class))
            ->andReturn(true);
        $events->shouldReceive('dispatch')
            ->once()
            ->with('eloquent.deleted: ' . get_class($address), Mockery::type(Address::class));
274

275 276 277 278 279
        $address->delete();

        $this->assertEquals(2, $user->addresses()->count());
        $this->assertEquals(2, $user->addresses->count());

280 281
        $address->unsetEventDispatcher();

282 283 284 285 286 287 288 289
        $address = $user->addresses->first();
        $address->delete();

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(1, $user->addresses()->count());
        $this->assertEquals(1, $user->addresses->count());
    }

290 291
    public function testEmbedsManyDissociate()
    {
292 293
        $user = User::create([]);
        $cordoba = $user->addresses()->create(['city' => 'Cordoba']);
294 295 296 297 298 299 300 301 302 303

        $user->addresses()->dissociate($cordoba->id);

        $freshUser = User::find($user->id);
        $this->assertEquals(0, $user->addresses->count());
        $this->assertEquals(1, $freshUser->addresses->count());
    }

    public function testEmbedsManyAliases()
    {
304 305
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'London']);
306 307

        $address = $user->addresses()->attach($address);
Pooya Parsa's avatar
Pooya Parsa committed
308
        $this->assertEquals(['London'], $user->addresses->pluck('city')->all());
309 310

        $user->addresses()->detach($address);
Pooya Parsa's avatar
Pooya Parsa committed
311
        $this->assertEquals([], $user->addresses->pluck('city')->all());
312 313 314 315
    }

    public function testEmbedsManyCreatingEventReturnsFalse()
    {
316 317
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'London']);
318

Jens Segers's avatar
Jens Segers committed
319
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
320
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
321 322 323 324 325 326 327 328
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($address), $address)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.creating: ' . get_class($address), $address)
            ->andReturn(false);
329 330

        $this->assertFalse($user->addresses()->save($address));
331
        $address->unsetEventDispatcher();
332 333 334 335
    }

    public function testEmbedsManySavingEventReturnsFalse()
    {
336 337
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'Paris']);
338 339
        $address->exists = true;

Jens Segers's avatar
Jens Segers committed
340
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
341
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
342 343 344 345
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($address), $address)
            ->andReturn(false);
346 347

        $this->assertFalse($user->addresses()->save($address));
348
        $address->unsetEventDispatcher();
349 350 351 352
    }

    public function testEmbedsManyUpdatingEventReturnsFalse()
    {
353 354
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'New York']);
355 356
        $user->addresses()->save($address);

Jens Segers's avatar
Jens Segers committed
357
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
358
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
359 360 361 362 363 364 365 366
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($address), $address)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.updating: ' . get_class($address), $address)
            ->andReturn(false);
367 368 369 370

        $address->city = 'Warsaw';

        $this->assertFalse($user->addresses()->save($address));
371
        $address->unsetEventDispatcher();
372 373 374 375
    }

    public function testEmbedsManyDeletingEventReturnsFalse()
    {
376 377
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->save(new Address(['city' => 'New York']));
378 379 380

        $address = $user->addresses->first();

Jens Segers's avatar
Jens Segers committed
381
        $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
382
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
Jens Segers's avatar
Jens Segers committed
383 384 385 386
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.deleting: ' . get_class($address), Mockery::mustBe($address))
            ->andReturn(false);
387 388

        $this->assertEquals(0, $user->addresses()->destroy($address));
Pooya Parsa's avatar
Pooya Parsa committed
389
        $this->assertEquals(['New York'], $user->addresses->pluck('city')->all());
390 391

        $address->unsetEventDispatcher();
392 393 394 395
    }

    public function testEmbedsManyFindOrContains()
    {
396 397 398
        $user = User::create(['name' => 'John Doe']);
        $address1 = $user->addresses()->save(new Address(['city' => 'New York']));
        $address2 = $user->addresses()->save(new Address(['city' => 'Paris']));
399 400 401 402 403 404 405 406 407 408 409 410 411

        $address = $user->addresses()->find($address1->_id);
        $this->assertEquals($address->city, $address1->city);

        $address = $user->addresses()->find($address2->_id);
        $this->assertEquals($address->city, $address2->city);

        $this->assertTrue($user->addresses()->contains($address2->_id));
        $this->assertFalse($user->addresses()->contains('123'));
    }

    public function testEmbedsManyEagerLoading()
    {
412 413 414
        $user1 = User::create(['name' => 'John Doe']);
        $user1->addresses()->save(new Address(['city' => 'New York']));
        $user1->addresses()->save(new Address(['city' => 'Paris']));
415

416 417 418
        $user2 = User::create(['name' => 'Jane Doe']);
        $user2->addresses()->save(new Address(['city' => 'Berlin']));
        $user2->addresses()->save(new Address(['city' => 'Paris']));
419 420 421

        $user = User::find($user1->id);
        $relations = $user->getRelations();
Gabriel Caruso's avatar
Gabriel Caruso committed
422
        $this->assertArrayNotHasKey('addresses', $relations);
423
        $this->assertArrayHasKey('addresses', $user->toArray());
424
        $this->assertIsArray($user->toArray()['addresses']);
425 426 427

        $user = User::with('addresses')->get()->first();
        $relations = $user->getRelations();
Gabriel Caruso's avatar
Gabriel Caruso committed
428
        $this->assertArrayHasKey('addresses', $relations);
429
        $this->assertEquals(2, $relations['addresses']->count());
430
        $this->assertArrayHasKey('addresses', $user->toArray());
431
        $this->assertIsArray($user->toArray()['addresses']);
432 433
    }

434
    public function testEmbedsManyDeleteAll()
435
    {
436 437 438
        $user1 = User::create(['name' => 'John Doe']);
        $user1->addresses()->save(new Address(['city' => 'New York']));
        $user1->addresses()->save(new Address(['city' => 'Paris']));
439

440 441 442
        $user2 = User::create(['name' => 'Jane Doe']);
        $user2->addresses()->save(new Address(['city' => 'Berlin']));
        $user2->addresses()->save(new Address(['city' => 'Paris']));
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459

        $user1->addresses()->delete();
        $this->assertEquals(0, $user1->addresses()->count());
        $this->assertEquals(0, $user1->addresses->count());
        $this->assertEquals(2, $user2->addresses()->count());
        $this->assertEquals(2, $user2->addresses->count());

        $user1 = User::find($user1->id);
        $user2 = User::find($user2->id);
        $this->assertEquals(0, $user1->addresses()->count());
        $this->assertEquals(0, $user1->addresses->count());
        $this->assertEquals(2, $user2->addresses()->count());
        $this->assertEquals(2, $user2->addresses->count());
    }

    public function testEmbedsManyCollectionMethods()
    {
460
        $user = User::create(['name' => 'John Doe']);
Jens Segers's avatar
Jens Segers committed
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
        $user->addresses()->save(new Address([
            'city' => 'Paris',
            'country' => 'France',
            'visited' => 4,
            'created_at' => new DateTime('3 days ago'),
        ]));
        $user->addresses()->save(new Address([
            'city' => 'Bruges',
            'country' => 'Belgium',
            'visited' => 7,
            'created_at' => new DateTime('5 days ago'),
        ]));
        $user->addresses()->save(new Address([
            'city' => 'Brussels',
            'country' => 'Belgium',
            'visited' => 2,
            'created_at' => new DateTime('4 days ago'),
        ]));
        $user->addresses()->save(new Address([
            'city' => 'Ghent',
            'country' => 'Belgium',
            'visited' => 13,
            'created_at' => new DateTime('2 days ago'),
        ]));
485

Pooya Parsa's avatar
Pooya Parsa committed
486
        $this->assertEquals(['Paris', 'Bruges', 'Brussels', 'Ghent'], $user->addresses()->pluck('city')->all());
Jens Segers's avatar
Jens Segers committed
487 488 489 490
        $this->assertEquals(['Bruges', 'Brussels', 'Ghent', 'Paris'], $user->addresses()
            ->sortBy('city')
            ->pluck('city')
            ->all());
Pooya Parsa's avatar
Pooya Parsa committed
491
        $this->assertEquals([], $user->addresses()->where('city', 'New York')->pluck('city')->all());
Jens Segers's avatar
Jens Segers committed
492 493 494 495 496 497 498 499 500
        $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()
            ->where('country', 'Belgium')
            ->pluck('city')
            ->all());
        $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()
            ->where('country', 'Belgium')
            ->sortBy('city')
            ->pluck('city')
            ->all());
501

502
        $results = $user->addresses->first();
Jens Segers's avatar
Jens Segers committed
503
        $this->assertInstanceOf(Address::class, $results);
504

505
        $results = $user->addresses()->where('country', 'Belgium');
Jens Segers's avatar
Jens Segers committed
506
        $this->assertInstanceOf(Collection::class, $results);
507 508
        $this->assertEquals(3, $results->count());

509
        $results = $user->addresses()->whereIn('visited', [7, 13]);
510
        $this->assertEquals(2, $results->count());
511 512 513 514
    }

    public function testEmbedsOne()
    {
515 516
        $user = User::create(['name' => 'John Doe']);
        $father = new User(['name' => 'Mark Doe']);
517

Jens Segers's avatar
Jens Segers committed
518
        $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
519
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
Jens Segers's avatar
Jens Segers committed
520 521 522 523 524 525 526 527
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($father), $father)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.creating: ' . get_class($father), $father)
            ->andReturn(true);
Stas's avatar
Stas committed
528 529
        $events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($father), $father);
        $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
530

531
        $father = $user->father()->save($father);
532
        $father->unsetEventDispatcher();
533

534
        $this->assertNotNull($user->father);
535
        $this->assertEquals('Mark Doe', $user->father->name);
Jens Segers's avatar
Jens Segers committed
536 537
        $this->assertInstanceOf(DateTime::class, $father->created_at);
        $this->assertInstanceOf(DateTime::class, $father->updated_at);
538
        $this->assertNotNull($father->_id);
539
        $this->assertIsString($father->_id);
540 541

        $raw = $father->getAttributes();
Jens Segers's avatar
Jens Segers committed
542
        $this->assertInstanceOf(ObjectId::class, $raw['_id']);
543

Jens Segers's avatar
Jens Segers committed
544
        $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
545
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
Jens Segers's avatar
Jens Segers committed
546 547 548 549 550 551 552 553
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($father), $father)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.updating: ' . get_class($father), $father)
            ->andReturn(true);
Stas's avatar
Stas committed
554 555
        $events->shouldReceive('dispatch')->once()->with('eloquent.updated: ' . get_class($father), $father);
        $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
556

557 558
        $father->name = 'Tom Doe';
        $user->father()->save($father);
559
        $father->unsetEventDispatcher();
560

561
        $this->assertNotNull($user->father);
562 563
        $this->assertEquals('Tom Doe', $user->father->name);

564
        $father = new User(['name' => 'Jim Doe']);
565

Jens Segers's avatar
Jens Segers committed
566
        $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
567
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
Jens Segers's avatar
Jens Segers committed
568 569 570 571 572 573 574 575
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.saving: ' . get_class($father), $father)
            ->andReturn(true);
        $events->shouldReceive('until')
            ->once()
            ->with('eloquent.creating: ' . get_class($father), $father)
            ->andReturn(true);
Stas's avatar
Stas committed
576 577
        $events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($father), $father);
        $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
578

579
        $father = $user->father()->save($father);
580
        $father->unsetEventDispatcher();
581

582
        $this->assertNotNull($user->father);
583 584 585
        $this->assertEquals('Jim Doe', $user->father->name);
    }

586 587
    public function testEmbedsOneAssociate()
    {
588 589
        $user = User::create(['name' => 'John Doe']);
        $father = new User(['name' => 'Mark Doe']);
590

Jens Segers's avatar
Jens Segers committed
591
        $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
Stas's avatar
Stas committed
592
        $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
593 594
        $events->shouldReceive('until')->times(0)->with('eloquent.saving: ' . get_class($father), $father);

595
        $father = $user->father()->associate($father);
596
        $father->unsetEventDispatcher();
597

598
        $this->assertNotNull($user->father);
599 600 601
        $this->assertEquals('Mark Doe', $user->father->name);
    }

Jens Segers's avatar
Jens Segers committed
602 603 604 605 606 607
    public function testEmbedsOneNullAssociation()
    {
        $user = User::create();
        $this->assertNull($user->father);
    }

608 609
    public function testEmbedsOneDelete()
    {
610 611
        $user = User::create(['name' => 'John Doe']);
        $father = $user->father()->save(new User(['name' => 'Mark Doe']));
612 613 614 615 616

        $user->father()->delete();
        $this->assertNull($user->father);
    }

617 618
    public function testEmbedsManyToArray()
    {
Simon Schaufelberger's avatar
Simon Schaufelberger committed
619
        /** @var User $user */
620 621 622 623
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->save(new Address(['city' => 'New York']));
        $user->addresses()->save(new Address(['city' => 'Paris']));
        $user->addresses()->save(new Address(['city' => 'Brussels']));
624 625

        $array = $user->toArray();
626
        $this->assertArrayHasKey('addresses', $array);
627
        $this->assertIsArray($array['addresses']);
628 629
    }

630 631
    public function testEmbeddedSave()
    {
Simon Schaufelberger's avatar
Simon Schaufelberger committed
632
        /** @var User $user */
633
        $user = User::create(['name' => 'John Doe']);
Simon Schaufelberger's avatar
Simon Schaufelberger committed
634
        /** @var \Address $address */
635 636
        $address = $user->addresses()->create(['city' => 'New York']);
        $father = $user->father()->create(['name' => 'Mark Doe']);
637 638 639 640 641 642 643 644 645 646 647 648 649

        $address->city = 'Paris';
        $address->save();

        $father->name = 'Steve Doe';
        $father->save();

        $this->assertEquals('Paris', $user->addresses->first()->city);
        $this->assertEquals('Steve Doe', $user->father->name);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals('Paris', $user->addresses->first()->city);
        $this->assertEquals('Steve Doe', $user->father->name);
Jens Segers's avatar
Jens Segers committed
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665

        $address = $user->addresses()->first();
        $father = $user->father;

        $address->city = 'Ghent';
        $address->save();

        $father->name = 'Mark Doe';
        $father->save();

        $this->assertEquals('Ghent', $user->addresses->first()->city);
        $this->assertEquals('Mark Doe', $user->father->name);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals('Ghent', $user->addresses->first()->city);
        $this->assertEquals('Mark Doe', $user->father->name);
666 667
    }

668 669
    public function testNestedEmbedsOne()
    {
670 671 672 673
        $user = User::create(['name' => 'John Doe']);
        $father = $user->father()->create(['name' => 'Mark Doe']);
        $grandfather = $father->father()->create(['name' => 'Steve Doe']);
        $greatgrandfather = $grandfather->father()->create(['name' => 'Tom Doe']);
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697

        $user->name = 'Tim Doe';
        $user->save();

        $father->name = 'Sven Doe';
        $father->save();

        $greatgrandfather->name = 'Ron Doe';
        $greatgrandfather->save();

        $this->assertEquals('Tim Doe', $user->name);
        $this->assertEquals('Sven Doe', $user->father->name);
        $this->assertEquals('Steve Doe', $user->father->father->name);
        $this->assertEquals('Ron Doe', $user->father->father->father->name);

        $user = User::where('name', 'Tim Doe')->first();
        $this->assertEquals('Tim Doe', $user->name);
        $this->assertEquals('Sven Doe', $user->father->name);
        $this->assertEquals('Steve Doe', $user->father->father->name);
        $this->assertEquals('Ron Doe', $user->father->father->father->name);
    }

    public function testNestedEmbedsMany()
    {
698 699 700 701 702 703
        $user = User::create(['name' => 'John Doe']);
        $country1 = $user->addresses()->create(['country' => 'France']);
        $country2 = $user->addresses()->create(['country' => 'Belgium']);
        $city1 = $country1->addresses()->create(['city' => 'Paris']);
        $city2 = $country2->addresses()->create(['city' => 'Ghent']);
        $city3 = $country2->addresses()->create(['city' => 'Brussels']);
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719

        $city3->city = 'Bruges';
        $city3->save();

        $this->assertEquals(2, $user->addresses()->count());
        $this->assertEquals(1, $user->addresses()->first()->addresses()->count());
        $this->assertEquals(2, $user->addresses()->last()->addresses()->count());

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(2, $user->addresses()->count());
        $this->assertEquals(1, $user->addresses()->first()->addresses()->count());
        $this->assertEquals(2, $user->addresses()->last()->addresses()->count());
    }

    public function testNestedMixedEmbeds()
    {
720 721 722 723
        $user = User::create(['name' => 'John Doe']);
        $father = $user->father()->create(['name' => 'Mark Doe']);
        $country1 = $father->addresses()->create(['country' => 'France']);
        $country2 = $father->addresses()->create(['country' => 'Belgium']);
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740

        $country2->country = 'England';
        $country2->save();

        $father->name = 'Steve Doe';
        $father->save();

        $this->assertEquals('France', $user->father->addresses()->first()->country);
        $this->assertEquals('England', $user->father->addresses()->last()->country);
        $this->assertEquals('Steve Doe', $user->father->name);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals('France', $user->father->addresses()->first()->country);
        $this->assertEquals('England', $user->father->addresses()->last()->country);
        $this->assertEquals('Steve Doe', $user->father->name);
    }

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
    public function testNestedEmbedsOneDelete()
    {
        $user = User::create(['name' => 'John Doe']);
        $father = $user->father()->create(['name' => 'Mark Doe']);
        $grandfather = $father->father()->create(['name' => 'Steve Doe']);
        $greatgrandfather = $grandfather->father()->create(['name' => 'Tom Doe']);

        $grandfather->delete();

        $this->assertNull($user->father->father);

        $user = User::where(['name' => 'John Doe'])->first();
        $this->assertNull($user->father->father);
    }

    public function testNestedEmbedsManyDelete()
    {
        $user = User::create(['name' => 'John Doe']);
        $country = $user->addresses()->create(['country' => 'France']);
        $city1 = $country->addresses()->create(['city' => 'Paris']);
        $city2 = $country->addresses()->create(['city' => 'Nice']);
        $city3 = $country->addresses()->create(['city' => 'Lyon']);

        $city2->delete();

        $this->assertEquals(2, $user->addresses()->first()->addresses()->count());
        $this->assertEquals('Lyon', $country->addresses()->last()->city);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(2, $user->addresses()->first()->addresses()->count());
        $this->assertEquals('Lyon', $country->addresses()->last()->city);
    }

    public function testNestedMixedEmbedsDelete()
    {
        $user = User::create(['name' => 'John Doe']);
        $father = $user->father()->create(['name' => 'Mark Doe']);
        $country1 = $father->addresses()->create(['country' => 'France']);
        $country2 = $father->addresses()->create(['country' => 'Belgium']);

        $country1->delete();

        $this->assertEquals(1, $user->father->addresses()->count());
        $this->assertEquals('Belgium', $user->father->addresses()->last()->country);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(1, $user->father->addresses()->count());
        $this->assertEquals('Belgium', $user->father->addresses()->last()->country);
    }

Jens Segers's avatar
Jens Segers committed
791 792
    public function testDoubleAssociate()
    {
793 794
        $user = User::create(['name' => 'John Doe']);
        $address = new Address(['city' => 'Paris']);
Jens Segers's avatar
Jens Segers committed
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810

        $user->addresses()->associate($address);
        $user->addresses()->associate($address);
        $address = $user->addresses()->first();
        $user->addresses()->associate($address);
        $this->assertEquals(1, $user->addresses()->count());

        $user = User::where('name', 'John Doe')->first();
        $user->addresses()->associate($address);
        $this->assertEquals(1, $user->addresses()->count());

        $user->save();
        $user->addresses()->associate($address);
        $this->assertEquals(1, $user->addresses()->count());
    }

Jens Segers's avatar
Jens Segers committed
811 812
    public function testSaveEmptyModel()
    {
813
        $user = User::create(['name' => 'John Doe']);
Jens Segers's avatar
Jens Segers committed
814 815
        $user->addresses()->save(new Address);
        $this->assertNotNull($user->addresses);
Jens Segers's avatar
Jens Segers committed
816
        $this->assertEquals(1, $user->addresses()->count());
Jens Segers's avatar
Jens Segers committed
817 818
    }

Jens Segers's avatar
Jens Segers committed
819 820
    public function testIncrementEmbedded()
    {
821 822
        $user = User::create(['name' => 'John Doe']);
        $address = $user->addresses()->create(['city' => 'New York', 'visited' => 5]);
Jens Segers's avatar
Jens Segers committed
823 824 825 826 827 828 829

        $address->increment('visited');
        $this->assertEquals(6, $address->visited);
        $this->assertEquals(6, $user->addresses()->first()->visited);

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(6, $user->addresses()->first()->visited);
830

831 832 833
        $user = User::where('name', 'John Doe')->first();
        $address = $user->addresses()->first();

834 835
        $address->decrement('visited');
        $this->assertEquals(5, $address->visited);
836
        $this->assertEquals(5, $user->addresses()->first()->visited);
837 838 839

        $user = User::where('name', 'John Doe')->first();
        $this->assertEquals(5, $user->addresses()->first()->visited);
Jens Segers's avatar
Jens Segers committed
840 841
    }

842 843
    public function testPaginateEmbedsMany()
    {
844 845 846 847
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->save(new Address(['city' => 'New York']));
        $user->addresses()->save(new Address(['city' => 'Paris']));
        $user->addresses()->save(new Address(['city' => 'Brussels']));
848 849 850

        $results = $user->addresses()->paginate(2);
        $this->assertEquals(2, $results->count());
851
        $this->assertEquals(3, $results->total());
852
    }
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871

    public function testGetQueueableRelationsEmbedsMany()
    {
        $user = User::create(['name' => 'John Doe']);
        $user->addresses()->save(new Address(['city' => 'New York']));
        $user->addresses()->save(new Address(['city' => 'Paris']));

        $this->assertEquals(['addresses'], $user->getQueueableRelations());
        $this->assertEquals([], $user->addresses->getQueueableRelations());
    }

    public function testGetQueueableRelationsEmbedsOne()
    {
        $user = User::create(['name' => 'John Doe']);
        $user->father()->save(new User(['name' => 'Mark Doe']));

        $this->assertEquals(['father'], $user->getQueueableRelations());
        $this->assertEquals([], $user->father->getQueueableRelations());
    }
872
}