Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/eager loading fail #160

Merged
merged 3 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions TestSetup/Database/Seeders/HousesSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function run()
"_key": "lannister",
"name": "Lannister",
"location_id": "king-s-landing",
"led_by": "TywinLannister",
"en": {
"description": "House Lannister of Casterly Rock is one of the Great Houses of Westeros, one of its richest and most powerful families and one of its oldest dynasties. It was also the royal House of the Seven Kingdoms following the extinction of House Baratheon of King\'s Landing, which had been their puppet House during the War of the Five Kings, for a brief stint of time until House Targaryen took back the Iron Throne in Daenerys Targaryen\'s war for Westeros."
}
Expand All @@ -27,13 +28,15 @@ public function run()
"_key": "stark",
"name": "Stark",
"location_id": "winterfell",
"led_by": "NedStark",
"en": {
"description": "House Stark of Winterfell is a Great House of Westeros and the royal house of the Kingdom of the North. They rule over the vast region known as the North from their seat in Winterfell. It is one of the oldest lines of Westerosi nobility by far, claiming a line of descent stretching back over eight thousand years. Before the Targaryen conquest, as well as during the War of the Five Kings and early on in Daenerys Targaryen\'s war for Westeros, the leaders of House Stark ruled over the region as the Kings in the North."
}
},
{
"_key": "targaryen",
"name": "Targaryen",
"led_by": "DaenerysTargaryen",
"location_id": "dragonstone",
"en": {
"coat-of-arms": "A three-headed dragon breathing flames, red on black (Sable, a dragon thrice-headed gules)",
Expand Down
22 changes: 22 additions & 0 deletions src/Eloquent/Relations/Concerns/IsAranguentRelation.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@

trait IsAranguentRelation
{
/**
* Get all of the primary keys for an array of models.
*
* @param array<mixed> $models
* @param string|null $key
* @return array<int, int|string>
*/
protected function getKeys(array $models, $key = null)
{
// The original function orders the results associatively by value which means the keys reorder too.
// However, a list of keys with unordered numeric keys will be recognized as an object down the line
// for json casting while we need a list of keys.

$keys = collect($models)->map(function ($value) use ($key) {
return $key ? $value->getAttribute($key) : $value->getKey();
})->values()->unique(null, true)->all();

sort($keys);

return $keys;
}

/**
* Add the constraints for a relationship count query.
*
Expand Down
114 changes: 0 additions & 114 deletions src/Testing/Concerns/InteractsWithDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,122 +5,9 @@
namespace LaravelFreelancerNL\Aranguent\Testing\Concerns;

use Illuminate\Support\Facades\DB;
use Illuminate\Testing\Constraints\HasInDatabase;
use Illuminate\Testing\Constraints\NotSoftDeletedInDatabase;
use Illuminate\Testing\Constraints\SoftDeletedInDatabase;
use PHPUnit\Framework\Constraint\LogicalNot as ReverseConstraint;

trait InteractsWithDatabase
{
/**
* Assert that a given where condition exists in the database.
*
* @param \Illuminate\Database\Eloquent\Model|string $table
* @param array<mixed> $data
* @param string|null $connection
* @return $this
*/
protected function assertDatabaseHas($table, array $data, $connection = null)
{
$this->assertThat(
$this->getTable($table),
new HasInDatabase($this->getConnection($connection), associativeFlatten($data)),
);

return $this;
}

/**
* Assert that a given where condition does not exist in the database.
*
* @param \Illuminate\Database\Eloquent\Model|string $table
* @param array<mixed> $data
* @param string|null $connection
* @return $this
*/
protected function assertDatabaseMissing($table, array $data, $connection = null)
{
$constraint = new ReverseConstraint(
new HasInDatabase($this->getConnection($connection), associativeFlatten($data)),
);

$this->assertThat($this->getTable($table), $constraint);

return $this;
}

/**
* Assert the given record has been "soft deleted".
*
* @param \Illuminate\Database\Eloquent\Model|string $table
* @param array<mixed> $data
* @param string|null $connection
* @param string|null $deletedAtColumn
* @return $this
*/
protected function assertSoftDeleted(
$table,
array $data = [],
$connection = null,
$deletedAtColumn = 'deleted_at',
) {
if ($this->isSoftDeletableModel($table) && !is_string($table)) {
return $this->assertSoftDeleted(
$table->getTable(),
[$table->getKeyName() => $table->getKey()],
$table->getConnectionName(), /** @phpstan-ignore-next-line */
$table->getDeletedAtColumn(),
);
}

$this->assertThat(
$this->getTable($table),
new SoftDeletedInDatabase(
$this->getConnection($connection),
associativeFlatten($data),
(string) $deletedAtColumn,
),
);

return $this;
}

/**
* Assert the given record has not been "soft deleted".
*
* @param \Illuminate\Database\Eloquent\Model|string $table
* @param array<mixed> $data
* @param string|null $connection
* @param string|null $deletedAtColumn
* @return $this
*/
protected function assertNotSoftDeleted(
$table,
array $data = [],
$connection = null,
$deletedAtColumn = 'deleted_at',
) {
if ($this->isSoftDeletableModel($table) && !is_string($table)) {
return $this->assertNotSoftDeleted(
$table->getTable(),
[$table->getKeyName() => $table->getKey()],
$table->getConnectionName(), /** @phpstan-ignore-next-line */
$table->getDeletedAtColumn(),
);
}

$this->assertThat(
$this->getTable($table),
new NotSoftDeletedInDatabase(
$this->getConnection($connection),
associativeFlatten($data),
(string) $deletedAtColumn,
),
);

return $this;
}

/**
* Cast a JSON string to a database compatible type.
* Supported for backwards compatibility in existing projects.
Expand All @@ -133,5 +20,4 @@ public function castAsJson($value)
{
return DB::raw($value);
}

}
30 changes: 28 additions & 2 deletions tests/Eloquent/BelongsToManyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
test('attach', function () {
$child = Character::find('JonSnow');

$lyannaStark = Character::firstOrCreate(
Character::firstOrCreate(
[
'id' => 'LyannaStark',
'name' => 'Lyanna',
Expand All @@ -68,7 +68,7 @@
$child->parents()->attach($lyannaStark);
$child->save();

$reloadedChild = Character::find('JonSnow');
Character::find('JonSnow');
$parents = $child->parents;

expect($parents[0]->id)->toEqual('NedStark');
Expand Down Expand Up @@ -157,3 +157,29 @@
expect($char->tags[1]->pivot->tag_id)->toBeString();
expect($char->tags[1]->pivot->tag_id)->toBe('2');
});

test('with', function () {
$parent = Character::with('children')->find('NedStark');

expect($parent->children)->toHaveCount(5);
expect($parent->children->first()->id)->toEqual('RobbStark');
});

test('with on multiple models', function () {
$characters = Character::with('children')->where('surname', 'Stark')->get();

expect($characters)->toHaveCount(6);
expect($characters[0]->id)->toEqual('NedStark');
expect($characters[0]->children->first()->id)->toEqual('AryaStark');
expect($characters[0]->children)->toHaveCount(5);
expect($characters[1]->id)->toEqual('CatelynStark');
expect($characters[1]->children)->toHaveCount(4);
});

test('load', function () {
$parent = Character::find('NedStark');
$parent->load('children');

expect($parent->children)->toHaveCount(5);
expect($parent->children->first()->id)->toEqual('RobbStark');
});
27 changes: 27 additions & 0 deletions tests/Eloquent/BelongsToTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use LaravelFreelancerNL\Aranguent\Testing\DatabaseTransactions;
use Mockery as M;
use TestSetup\Models\Character;
use TestSetup\Models\House;
use TestSetup\Models\Location;

uses(
Expand Down Expand Up @@ -82,3 +83,29 @@
expect($location->leader)->toBeInstanceOf(Character::class);
expect($location->leader->id)->toEqual('SansaStark');
});


test('with on single model', function () {
$house = House::with('head')->find('lannister');

expect($house->head)->toBeInstanceOf(Character::class);
expect($house->head->id)->toEqual('TywinLannister');
});


test('with on multiple model', function () {
$houses = House::with('head')->get();

expect($houses->count())->toBe(3);
expect($houses->first()->head)->toBeInstanceOf(Character::class);
expect($houses->first()->head->id)->toEqual('TywinLannister');
});


test('load', function () {
$house = House::find('lannister');
$house->load('head');

expect($house->head)->toBeInstanceOf(Character::class);
expect($house->head->id)->toEqual('TywinLannister');
});
8 changes: 8 additions & 0 deletions tests/Eloquent/HasManyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,11 @@
expect($location->inhabitants->first())->toBeInstanceOf(Character::class);
expect($location->inhabitants->first()->id)->toEqual('NedStark');
});

test('with on multiple models', function () {
$locations = Location::with('inhabitants')->get();

expect($locations->first()->inhabitants->first())->toBeInstanceOf(Character::class);
expect($locations->first()->inhabitants)->toHaveCount(2);
expect($locations[8]->inhabitants)->toHaveCount(0);
});
33 changes: 21 additions & 12 deletions tests/Query/WheresTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,29 @@
);
});

test('where in', function () {
$builder = getBuilder();
test('whereIn', function () {
$results = DB::table('characters')
->whereIn(
'characters.residence_id',
[
"astapor",
"beyond-the-wall",
"dragonstone",
"king-s-landing",
"riverrun",
"the-red-keep",
"vaes-dothrak",
"winterfell",
"yunkai",
],
)->get();

expect($results)->toHaveCount(33);
expect($results->first()->_id)->toBe('characters/NedStark');
expect($results->first()->residence_id)->toBe('winterfell');
});

$builder->select()
->from('users')
->whereIn('country', ['The Netherlands', 'Germany', 'Great-Britain']);

$this->assertSame(
'FOR userDoc IN users FILTER `userDoc`.`country` IN @'
. $builder->getQueryId()
. '_where_1 RETURN userDoc',
$builder->toSql(),
);
});

test('where integer in raw', function () {
$builder = getBuilder();
Expand Down
1 change: 1 addition & 0 deletions tests/Testing/InteractsWithDatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@

test('assert model exists', function () {
$ned = Character::find('NedStark');

$this->assertModelExists($ned);
});

Expand Down
Loading