diff options
Diffstat (limited to 'main/app/sprinkles/core/tests')
4 files changed, 1582 insertions, 1582 deletions
diff --git a/main/app/sprinkles/core/tests/Integration/DatabaseTests.php b/main/app/sprinkles/core/tests/Integration/DatabaseTests.php index 6f7c63e..b50f418 100644 --- a/main/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/main/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -1,1271 +1,1271 @@ -<?php - -namespace UserFrosting\Tests\Integration; - -use Exception; - -use UserFrosting\Tests\TestCase; -use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Database\Capsule\Manager as DB; - -use UserFrosting\Sprinkle\Core\Database\Models\Model; - -use Illuminate\Database\Eloquent\Relations\Relation; - -class DatabaseTests extends TestCase -{ - protected $schemaName = 'test_integration'; - - /** - * Setup the database schema. - * - * @return void - */ - public function setUp() { - // Boot parent TestCase, which will set up the database and connections for us. - parent::setUp(); - - // Boot database - $this->ci->db; - - $this->createSchema(); - } - - protected function createSchema() { - $this->schema($this->schemaName)->create('users', function ($table) { - $table->increments('id'); - $table->string('name')->nullable(); - }); - - // Users have multiple email addresses - $this->schema($this->schemaName)->create('emails', function ($table) { - $table->increments('id'); - $table->integer('user_id'); - $table->string('label'); - $table->string('email'); - }); - - // Users have multiple phones (polymorphic - other entities can have phones as well) - $this->schema($this->schemaName)->create('phones', function ($table) { - $table->increments('id'); - $table->string('label'); - $table->string('number', 20); - $table->morphs('phoneable'); - }); - - // Users have multiple roles... (m:m) - $this->schema($this->schemaName)->create('role_users', function ($table) { - $table->integer('user_id')->unsigned(); - $table->integer('role_id')->unsigned(); - }); - - $this->schema($this->schemaName)->create('roles', function ($table) { - $table->increments('id'); - $table->string('slug'); - }); - - // And Roles have multiple permissions... (m:m) - $this->schema($this->schemaName)->create('permission_roles', function ($table) { - $table->integer('permission_id')->unsigned(); - $table->integer('role_id')->unsigned(); - }); - - $this->schema($this->schemaName)->create('permissions', function ($table) { - $table->increments('id'); - $table->string('slug'); - }); - - // A user can be assigned to a specific task at a specific location - $this->schema($this->schemaName)->create('tasks', function ($table) { - $table->increments('id'); - $table->string('name'); - }); - - $this->schema($this->schemaName)->create('locations', function ($table) { - $table->increments('id'); - $table->string('name'); - }); - - $this->schema($this->schemaName)->create('assignments', function ($table) { - $table->integer('task_id')->unsigned(); - $table->integer('location_id')->unsigned(); - $table->morphs('assignable'); - }); - - $this->schema($this->schemaName)->create('jobs', function ($table) { - $table->integer('user_id')->unsigned(); - $table->integer('location_id')->unsigned(); - $table->integer('role_id')->unsigned(); - $table->string('title'); - }); - } - - /** - * Tear down the database schema. - * - * @return void - */ - public function tearDown() { - $this->schema($this->schemaName)->drop('users'); - $this->schema($this->schemaName)->drop('emails'); - $this->schema($this->schemaName)->drop('phones'); - $this->schema($this->schemaName)->drop('role_users'); - $this->schema($this->schemaName)->drop('roles'); - $this->schema($this->schemaName)->drop('permission_roles'); - $this->schema($this->schemaName)->drop('permissions'); - $this->schema($this->schemaName)->drop('tasks'); - $this->schema($this->schemaName)->drop('locations'); - $this->schema($this->schemaName)->drop('assignments'); - - Relation::morphMap([], FALSE); - } - - /** - * Tests... - */ - public function testOneToManyRelationship() { - $user = EloquentTestUser::create(['name' => 'David']); - $user->emails()->create([ - 'label' => 'primary', - 'email' => 'david@owlfancy.com' - ]); - $user->emails()->create([ - 'label' => 'work', - 'email' => 'david@attenboroughsreef.com' - ]); - - $emails = $user->emails; - - $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $emails); - $this->assertEquals(2, $emails->count()); - $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[0]); - $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[1]); - } - - /** - * Tests our custom HasManySyncable class. - */ - public function testSyncOneToMany() { - $user = EloquentTestUser::create(['name' => 'David']); - // Set up original emails - $user->emails()->create([ - 'id' => 1, - 'label' => 'primary', - 'email' => 'david@owlfancy.com' - ]); - $user->emails()->create([ - 'id' => 2, - 'label' => 'work', - 'email' => 'david@attenboroughsreef.com' - ]); - - // Delete `work`, update `primary`, and add `gmail` - $user->emails()->sync([ - [ - 'id' => 1, - 'email' => 'david@aol.com' - ], - [ - 'label' => 'gmail', - 'email' => 'davidattenborough@gmail.com' - ] - ]); - - $emails = $user->emails->toArray(); - - $this->assertEquals([ - [ - 'id' => 1, - 'user_id' => 1, - 'label' => 'primary', - 'email' => 'david@aol.com' - ], - [ - 'id' => 3, - 'user_id' => 1, - 'label' => 'gmail', - 'email' => 'davidattenborough@gmail.com' - ] - ], $emails); - } - - /** - * Tests our custom MorphManySyncable class. - */ - public function testSyncMorphMany() { - $user = EloquentTestUser::create(['name' => 'David']); - // Set up original phones - $user->phones()->create([ - 'id' => 1, - 'label' => 'primary', - 'number' => '5555551212' - ]); - $user->phones()->create([ - 'id' => 2, - 'label' => 'work', - 'number' => '2223334444' - ]); - - // Delete `work`, update `primary`, and add `fax` - $user->phones()->sync([ - [ - 'id' => 1, - 'number' => '8883332222' - ], - [ - 'label' => 'fax', - 'number' => '5550005555' - ] - ]); - - $phones = $user->phones->toArray(); - - $this->assertEquals([ - [ - 'id' => 1, - 'phoneable_id' => 1, - 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', - 'label' => 'primary', - 'number' => '8883332222' - ], - [ - 'id' => 3, - 'phoneable_id' => 1, - 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', - 'label' => 'fax', - 'number' => '5550005555' - ] - ], $phones); - } - - public function testBelongsToManyUnique() { - $user = EloquentTestUser::create(['name' => 'David']); - - $this->generateLocations(); - $this->generateRoles(); - $this->generateJobs(); - - $expectedRoles = [ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 2 - ] - ], - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 3 - ] - ] - ]; - - $roles = $user->jobRoles; - $this->assertEquals($expectedRoles, $roles->toArray()); - - // Test eager loading - $users = EloquentTestUser::with('jobRoles')->get(); - $this->assertEquals($expectedRoles, $users->toArray()[0]['job_roles']); - } - - public function testMorphsToManyUnique() { - $user = EloquentTestUser::create(['name' => 'David']); - $user2 = EloquentTestUser::create(['name' => 'Alex']); - - $this->generateTasks(); - $this->generateLocations(); - $this->generateAssignments(); - - $expectedTasks = [ - [ - 'id' => 2, - 'name' => 'Chopping', - 'pivot' => [ - 'assignable_id' => 1, - 'task_id' => 2 - ] - ], - [ - 'id' => 3, - 'name' => 'Baleing', - 'pivot' => [ - 'assignable_id' => 1, - 'task_id' => 3 - ] - ] - ]; - - $tasks = $user->assignmentTasks; - $this->assertEquals($expectedTasks, $tasks->toArray()); - - // Test eager loading - $users = EloquentTestUser::with('assignmentTasks')->get(); - $this->assertEquals($expectedTasks, $users->toArray()[0]['assignment_tasks']); - } - - public function testMorphsToManyUniqueWithTertiary() { - $user = EloquentTestUser::create(['name' => 'David']); - $user2 = EloquentTestUser::create(['name' => 'Alex']); - - $this->generateTasks(); - $this->generateLocations(); - $this->generateAssignments(); - - $expectedTasks = [ - [ - 'id' => 2, - 'name' => 'Chopping', - 'pivot' => [ - 'assignable_id' => 1, - 'task_id' => 2 - ], - 'locations' => [ - [ - 'id' => 1, - 'name' => 'Hatchery', - 'pivot' => [ - 'location_id' => 1, - 'task_id' => 2 - ], - ], - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'location_id' => 2, - 'task_id' => 2 - ], - ] - ] - ], - [ - 'id' => 3, - 'name' => 'Baleing', - 'pivot' => [ - 'assignable_id' => 1, - 'task_id' => 3 - ], - 'locations' => [ - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'location_id' => 2, - 'task_id' => 3 - ], - ] - ] - ] - ]; - - $tasks = $user->tasks; - $this->assertEquals($expectedTasks, $tasks->toArray()); - - // Test eager loading - $users = EloquentTestUser::with('tasks')->get(); - $this->assertEquals($expectedTasks, $users->toArray()[0]['tasks']); - } - - public function testBelongsToManyUniqueWithTertiary() { - $user = EloquentTestUser::create(['name' => 'David']); - - $this->generateLocations(); - $this->generateRoles(); - $this->generateJobs(); - - $expectedJobs = [ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 2 - ], - 'locations' => [ - [ - 'id' => 1, - 'name' => 'Hatchery', - 'pivot' => [ - 'title' => 'Grunt', - 'location_id' => 1, - 'role_id' => 2 - ] - ], - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'title' => 'Sergeant', - 'location_id' => 2, - 'role_id' => 2 - ] - ] - ] - ], - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 3 - ], - 'locations' => [ - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'title' => 'Queen', - 'location_id' => 2, - 'role_id' => 3 - ] - ] - ] - ] - ]; - - $jobs = $user->jobs()->withPivot('title')->get(); - $this->assertEquals($expectedJobs, $jobs->toArray()); - - // Test eager loading - $users = EloquentTestUser::with(['jobs' => function ($relation) { - return $relation->withPivot('title'); - }])->get(); - - $this->assertEquals($expectedJobs, $users->toArray()[0]['jobs']); - } - - public function testBelongsToManyUniqueWithTertiaryEagerLoad() { - $user1 = EloquentTestUser::create(['name' => 'David']); - $user2 = EloquentTestUser::create(['name' => 'Alex']); - - $this->generateLocations(); - $this->generateRoles(); - $this->generateJobs(); - - $users = EloquentTestUser::with('jobs')->get(); - - $this->assertEquals([ - [ - 'id' => 1, - 'name' => 'David', - 'jobs' => [ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 2 - ], - 'locations' => [ - [ - 'id' => 1, - 'name' => 'Hatchery', - 'pivot' => [ - 'location_id' => 1, - 'role_id' => 2 - ] - ], - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'location_id' => 2, - 'role_id' => 2 - ] - ] - ] - ], - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 3 - ], - 'locations' => [ - [ - 'id' => 2, - 'name' => 'Nexus', - 'pivot' => [ - 'location_id' => 2, - 'role_id' => 3 - ] - ] - ] - ] - ] - ], - [ - 'id' => 2, - 'name' => 'Alex', - 'jobs' => [ - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'user_id' => 2, - 'role_id' => 3 - ], - 'locations' => [ - [ - 'id' => 1, - 'name' => 'Hatchery', - 'pivot' => [ - 'location_id' => 1, - 'role_id' => 3 - ] - ], - ] - ] - ] - ] - ], $users->toArray()); - } - - /** - * Test the ability of a BelongsToManyThrough relationship to retrieve structured data on a single model or set of models. - */ - public function testBelongsToManyThrough() { - $this->generateRolesWithPermissions(); - - $user = EloquentTestUser::create(['name' => 'David']); - - $user->roles()->attach([1, 2]); - - // Test retrieval of via models as well - $this->assertEquals([ - [ - 'id' => 1, - 'slug' => 'uri_harvest', - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 1 - ] - ], - [ - 'id' => 2, - 'slug' => 'uri_spit_acid', - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 2 - ] - ], - [ - 'id' => 3, - 'slug' => 'uri_slash', - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 3 - ] - ] - ], $user->permissions->toArray()); - - // Test counting - $this->assertEquals(3, $user->permissions()->count()); - - $user2 = EloquentTestUser::create(['name' => 'Alex']); - $user2->roles()->attach([2, 3]); - - // Test eager load - $users = EloquentTestUser::with('permissions')->get(); - $usersWithPermissions = $users->toArray(); - - $this->assertEquals([ - [ - 'id' => 2, - 'slug' => 'uri_spit_acid', - 'pivot' => [ - 'user_id' => 2, - 'permission_id' => 2 - ] - ], - [ - 'id' => 3, - 'slug' => 'uri_slash', - 'pivot' => [ - 'user_id' => 2, - 'permission_id' => 3 - ] - ], - [ - 'id' => 4, - 'slug' => 'uri_royal_jelly', - 'pivot' => [ - 'user_id' => 2, - 'permission_id' => 4 - ] - ] - ], $usersWithPermissions[1]['permissions']); - - // Test counting related models (withCount) - $users = EloquentTestUser::withCount('permissions')->get(); - $this->assertEquals(3, $users[0]->permissions_count); - $this->assertEquals(3, $users[1]->permissions_count); - - $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[0]); - $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[1]); - $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[2]); - } - - /** - * Test the ability of a BelongsToManyThrough relationship to retrieve and count paginated queries. - */ - public function testBelongsToManyThroughPaginated() { - $this->generateRolesWithPermissions(); - - $user = EloquentTestUser::create(['name' => 'David']); - - $user->roles()->attach([1, 2]); - - $paginatedPermissions = $user->permissions()->take(2)->offset(1); - - $this->assertEquals([ - [ - 'id' => 2, - 'slug' => 'uri_spit_acid', - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 2 - ] - ], - [ - 'id' => 3, - 'slug' => 'uri_slash', - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 3 - ] - ] - ], $paginatedPermissions->get()->toArray()); - - $this->assertEquals(2, $paginatedPermissions->count()); - } - - /** - * Test the ability of a BelongsToManyThrough relationship to retrieve structured data on a single model or set of models, - * eager loading the "via" models at the same time. - */ - public function testBelongsToManyThroughWithVia() { - $this->generateRolesWithPermissions(); - - $user = EloquentTestUser::create(['name' => 'David']); - - $user->roles()->attach([1, 2]); - - // Test retrieval of via models as well - $this->assertBelongsToManyThroughForDavid($user->permissions()->withVia('roles_via')->get()->toArray()); - - $user2 = EloquentTestUser::create(['name' => 'Alex']); - $user2->roles()->attach([2, 3]); - - // Test eager loading - $users = EloquentTestUser::with(['permissions' => function ($query) { - return $query->withVia('roles_via'); - }])->get(); - - $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[0]); - $this->assertInstanceOf(EloquentTestRole::class, $users[0]->permissions[0]->roles_via[0]); - - $usersWithPermissions = $users->toArray(); - - $this->assertBelongsToManyThroughForDavid($usersWithPermissions[0]['permissions']); - $this->assertBelongsToManyThroughForAlex($usersWithPermissions[1]['permissions']); - } - - public function testQueryExclude() { - $this->generateRoles(); - $this->generateJobs(); - $job = EloquentTestJob::exclude('location_id', 'title')->first(); - - $this->assertEquals([ - 'role_id' => 2, - 'user_id' => 1 - ], $job->toArray()); - } - - - public function testQueryExcludeOnJoinedTable() { - $this->generateRolesWithPermissions(); - - $user = EloquentTestUser::create(['name' => 'David']); - - $user->roles()->attach([1, 2]); - - $users = EloquentTestUser::with(['permissions' => function ($query) { - $query->exclude('slug'); - }])->get(); - - $this->assertEquals([ - [ - 'id' => 1, - 'name' => 'David', - 'permissions' => [ - [ - 'id' => 1, - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 1 - ] - ], - [ - 'id' => 2, - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 2 - ] - ], - [ - 'id' => 3, - 'pivot' => [ - 'user_id' => 1, - 'permission_id' => 3 - ] - ] - ] - ] - ], $users->toArray()); - } - - public function testQueryExcludeUseQualifiedNamesOnJoinedTable() { - $this->generateRolesWithPermissions(); - - $user = EloquentTestUser::create(['name' => 'David']); - - $user->roles()->attach([1, 2]); - - $users = EloquentTestUser::with(['roles' => function ($query) { - $query->addSelect('roles.*', 'jobs.*')->leftJoin('jobs', 'jobs.role_id', '=', 'roles.id') - ->exclude('slug', 'jobs.user_id', 'jobs.location_id', 'jobs.role_id'); - }])->get(); - - $this->assertEquals([ - [ - 'id' => 1, - 'name' => 'David', - 'roles' => [ - [ - 'id' => 1, - 'title' => NULL, - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 1 - ] - ], - [ - 'id' => 2, - 'title' => NULL, - 'pivot' => [ - 'user_id' => 1, - 'role_id' => 2 - ] - ] - ] - ] - ], $users->toArray()); - } - - public function testQueryExcludeWildcard() { - $this->generateRoles(); - $this->generateJobs(); - $job = EloquentTestJob::select('*')->addSelect('user_id')->exclude('*')->first(); - - $this->assertEquals([ - 'user_id' => 1 - ], $job->toArray()); - - $job = EloquentTestJob::select('jobs.*')->addSelect('user_id')->exclude('*')->first(); - - $this->assertEquals([ - 'user_id' => 1 - ], $job->toArray()); - - $job = EloquentTestJob::select('*')->addSelect('user_id')->exclude('jobs.*')->first(); - - $this->assertEquals([ - 'user_id' => 1 - ], $job->toArray()); - } - - /** - * Helpers... - */ - - /** - * Get a database connection instance. - * - * @return \Illuminate\Database\Connection - */ - protected function connection($connection = 'test_integration') { - return Model::getConnectionResolver()->connection($connection); - } - - /** - * Get a schema builder instance. - * - * @return \Illuminate\Database\Schema\Builder - */ - protected function schema($connection = 'test_integration') { - return $this->connection($connection)->getSchemaBuilder(); - } - - protected function generateRoles() { - return [ - EloquentTestRole::create([ - 'id' => 1, - 'slug' => 'forager' - ]), - - EloquentTestRole::create([ - 'id' => 2, - 'slug' => 'soldier' - ]), - - EloquentTestRole::create([ - 'id' => 3, - 'slug' => 'egg-layer' - ]) - ]; - } - - protected function generatePermissions() { - return [ - EloquentTestPermission::create([ - 'id' => 1, - 'slug' => 'uri_harvest' - ]), - - EloquentTestPermission::create([ - 'id' => 2, - 'slug' => 'uri_spit_acid' - ]), - - EloquentTestPermission::create([ - 'id' => 3, - 'slug' => 'uri_slash' - ]), - - EloquentTestPermission::create([ - 'id' => 4, - 'slug' => 'uri_royal_jelly' - ]) - ]; - } - - protected function generateRolesWithPermissions() { - $roles = $this->generateRoles(); - - $this->generatePermissions(); - - $roles[0]->permissions()->attach([1, 2]); - // We purposefully want a permission that belongs to more than one role - $roles[1]->permissions()->attach([2, 3]); - $roles[2]->permissions()->attach([2, 4]); - - return $roles; - } - - protected function generateJobs() { - - /** - * Sample data - * - * | user_id | role_id | location_id | - * |---------|---------|-------------| - * | 1 | 2 | 1 | - * | 1 | 2 | 2 | - * | 1 | 3 | 2 | - * | 2 | 3 | 1 | - */ - - return [ - EloquentTestJob::create([ - 'role_id' => 2, - 'location_id' => 1, - 'user_id' => 1, - 'title' => 'Grunt' - ]), - EloquentTestJob::create([ - 'role_id' => 2, - 'location_id' => 2, - 'user_id' => 1, - 'title' => 'Sergeant' - ]), - EloquentTestJob::create([ - 'role_id' => 3, - 'location_id' => 2, - 'user_id' => 1, - 'title' => 'Queen' - ]), - EloquentTestJob::create([ - 'role_id' => 3, - 'location_id' => 1, - 'user_id' => 2, - 'title' => 'Demi-queen' - ]) - ]; - } - - protected function generateLocations() { - return [ - EloquentTestLocation::create([ - 'id' => 1, - 'name' => 'Hatchery' - ]), - - EloquentTestLocation::create([ - 'id' => 2, - 'name' => 'Nexus' - ]) - ]; - } - - protected function generateTasks() { - return [ - EloquentTestTask::create([ - 'id' => 1, - 'name' => 'Digging' - ]), - - EloquentTestTask::create([ - 'id' => 2, - 'name' => 'Chopping' - ]), - - EloquentTestTask::create([ - 'id' => 3, - 'name' => 'Baleing' - ]) - ]; - } - - protected function generateAssignments() { - return [ - EloquentTestAssignment::create([ - 'task_id' => 2, - 'location_id' => 1, - 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' - ]), - EloquentTestAssignment::create([ - 'task_id' => 2, - 'location_id' => 2, - 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' - ]), - EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 2, - 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' - ]), - EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 3, - 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestNonExistant' - ]), - EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 1, - 'assignable_id' => 2, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' - ]) - ]; - } - - protected function assertBelongsToManyThroughForDavid($permissions) { - // User should have effective permissions uri_harvest, uri_spit_acid, and uri_slash. - // We also check that the 'roles_via' relationship is properly set. - $this->assertEquals('uri_harvest', $permissions[0]['slug']); - $this->assertEquals([ - [ - 'id' => 1, - 'slug' => 'forager', - 'pivot' => [ - 'permission_id' => 1, - 'role_id' => 1 - ] - ] - ], $permissions[0]['roles_via']); - $this->assertEquals('uri_spit_acid', $permissions[1]['slug']); - $this->assertEquals([ - [ - 'id' => 1, - 'slug' => 'forager', - 'pivot' => [ - 'permission_id' => 2, - 'role_id' => 1 - ] - ], - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'permission_id' => 2, - 'role_id' => 2 - ] - ] - ], $permissions[1]['roles_via']); - $this->assertEquals('uri_slash', $permissions[2]['slug']); - $this->assertEquals([ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'permission_id' => 3, - 'role_id' => 2 - ] - ] - ], $permissions[2]['roles_via']); - } - - protected function assertBelongsToManyThroughForAlex($permissions) { - // User should have effective permissions uri_spit_acid, uri_slash, and uri_royal_jelly. - // We also check that the 'roles_via' relationship is properly set. - $this->assertEquals('uri_spit_acid', $permissions[0]['slug']); - $this->assertEquals([ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'permission_id' => 2, - 'role_id' => 2 - ] - ], - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'permission_id' => 2, - 'role_id' => 3 - ] - ] - ], $permissions[0]['roles_via']); - $this->assertEquals('uri_slash', $permissions[1]['slug']); - $this->assertEquals([ - [ - 'id' => 2, - 'slug' => 'soldier', - 'pivot' => [ - 'permission_id' => 3, - 'role_id' => 2 - ] - ] - ], $permissions[1]['roles_via']); - $this->assertEquals('uri_royal_jelly', $permissions[2]['slug']); - $this->assertEquals([ - [ - 'id' => 3, - 'slug' => 'egg-layer', - 'pivot' => [ - 'permission_id' => 4, - 'role_id' => 3 - ] - ] - ], $permissions[2]['roles_via']); - } -} - -/** - * Eloquent Models... - */ -class EloquentTestModel extends Model -{ - protected $connection = 'test_integration'; -} - -class EloquentTestUser extends EloquentTestModel -{ - protected $table = 'users'; - protected $guarded = []; - - public function emails() { - return $this->hasMany('UserFrosting\Tests\Integration\EloquentTestEmail', 'user_id'); - } - - public function phones() { - return $this->morphMany('UserFrosting\Tests\Integration\EloquentTestPhone', 'phoneable'); - } - - /** - * Get all roles to which this user belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany - */ - public function roles() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'role_users', 'user_id', 'role_id'); - } - - /** - * Get all of the permissions this user has, via its roles. - * - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough - */ - public function permissions() { - return $this->belongsToManyThrough( - 'UserFrosting\Tests\Integration\EloquentTestPermission', - 'UserFrosting\Tests\Integration\EloquentTestRole', - 'role_users', - 'user_id', - 'role_id', - 'permission_roles', - 'role_id', - 'permission_id' - ); - } - - /** - * Get all of the user's unique tasks. - */ - public function assignmentTasks() { - $relation = $this->morphToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestTask', - 'assignable', - 'assignments', - NULL, - 'task_id' // Need to explicitly set this, since it doesn't match our related model name - ); - - return $relation; - } - - /** - * Get all of the user's unique tasks along with the task locations. - */ - public function tasks() { - $relation = $this->morphToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestTask', - 'assignable', - 'assignments', - NULL, - 'task_id' // Need to explicitly set this, since it doesn't match our related model name - )->withTertiary(EloquentTestLocation::class, NULL, 'location_id'); - - return $relation; - } - - /** - * Get all of the user's unique roles based on their jobs. - */ - public function jobRoles() { - $relation = $this->belongsToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestRole', - 'jobs', - 'user_id', - 'role_id' - ); - - return $relation; - } - - /** - * Get all of the user's unique roles based on their jobs as a tertiary relationship. - */ - public function jobs() { - $relation = $this->belongsToManyUnique( - EloquentTestRole::class, - 'jobs', - 'user_id', - 'role_id' - )->withTertiary(EloquentTestLocation::class, NULL, 'location_id'); - - return $relation; - } -} - -class EloquentTestEmail extends EloquentTestModel -{ - protected $table = 'emails'; - protected $guarded = []; - - public function user() { - return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestUser', 'user_id'); - } -} - -class EloquentTestPhone extends EloquentTestModel -{ - protected $table = 'phones'; - protected $guarded = []; - - public function phoneable() { - return $this->morphTo(); - } -} - -class EloquentTestRole extends EloquentTestModel -{ - protected $table = 'roles'; - protected $guarded = []; - - /** - * Get a list of permissions assigned to this role. - */ - public function permissions() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestPermission', 'permission_roles', 'role_id', 'permission_id'); - } -} - -class EloquentTestPermission extends EloquentTestModel -{ - protected $table = 'permissions'; - protected $guarded = []; - - /** - * Get a list of roles that have this permission. - */ - public function roles() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'permission_roles', 'permission_id', 'role_id'); - } -} - -class EloquentTestTask extends EloquentTestModel -{ - protected $table = 'tasks'; - protected $guarded = []; - - public function locations() { - return $this->belongsToMany( - 'UserFrosting\Tests\Integration\EloquentTestLocation', - 'assignments', - 'task_id', - 'location_id' - ); - } -} - -class EloquentTestLocation extends EloquentTestModel -{ - protected $table = 'locations'; - protected $guarded = []; -} - -class EloquentTestAssignment extends EloquentTestModel -{ - protected $table = 'assignments'; - protected $guarded = []; - - /** - * Get all of the users that are assigned to this assignment. - */ - public function users() { - return $this->morphedByMany('UserFrosting\Tests\Integration\EloquentTestUser', 'assignable'); - } -} - -class EloquentTestJob extends EloquentTestModel -{ - protected $table = 'jobs'; - protected $guarded = []; - - /** - * Get the role for this job. - */ - public function role() { - return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestRole', 'role_id'); - } -} +<?php
+
+namespace UserFrosting\Tests\Integration;
+
+use Exception;
+
+use UserFrosting\Tests\TestCase;
+use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Database\Capsule\Manager as DB;
+
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+use Illuminate\Database\Eloquent\Relations\Relation;
+
+class DatabaseTests extends TestCase
+{
+ protected $schemaName = 'test_integration';
+
+ /**
+ * Setup the database schema.
+ *
+ * @return void
+ */
+ public function setUp() {
+ // Boot parent TestCase, which will set up the database and connections for us.
+ parent::setUp();
+
+ // Boot database
+ $this->ci->db;
+
+ $this->createSchema();
+ }
+
+ protected function createSchema() {
+ $this->schema($this->schemaName)->create('users', function ($table) {
+ $table->increments('id');
+ $table->string('name')->nullable();
+ });
+
+ // Users have multiple email addresses
+ $this->schema($this->schemaName)->create('emails', function ($table) {
+ $table->increments('id');
+ $table->integer('user_id');
+ $table->string('label');
+ $table->string('email');
+ });
+
+ // Users have multiple phones (polymorphic - other entities can have phones as well)
+ $this->schema($this->schemaName)->create('phones', function ($table) {
+ $table->increments('id');
+ $table->string('label');
+ $table->string('number', 20);
+ $table->morphs('phoneable');
+ });
+
+ // Users have multiple roles... (m:m)
+ $this->schema($this->schemaName)->create('role_users', function ($table) {
+ $table->integer('user_id')->unsigned();
+ $table->integer('role_id')->unsigned();
+ });
+
+ $this->schema($this->schemaName)->create('roles', function ($table) {
+ $table->increments('id');
+ $table->string('slug');
+ });
+
+ // And Roles have multiple permissions... (m:m)
+ $this->schema($this->schemaName)->create('permission_roles', function ($table) {
+ $table->integer('permission_id')->unsigned();
+ $table->integer('role_id')->unsigned();
+ });
+
+ $this->schema($this->schemaName)->create('permissions', function ($table) {
+ $table->increments('id');
+ $table->string('slug');
+ });
+
+ // A user can be assigned to a specific task at a specific location
+ $this->schema($this->schemaName)->create('tasks', function ($table) {
+ $table->increments('id');
+ $table->string('name');
+ });
+
+ $this->schema($this->schemaName)->create('locations', function ($table) {
+ $table->increments('id');
+ $table->string('name');
+ });
+
+ $this->schema($this->schemaName)->create('assignments', function ($table) {
+ $table->integer('task_id')->unsigned();
+ $table->integer('location_id')->unsigned();
+ $table->morphs('assignable');
+ });
+
+ $this->schema($this->schemaName)->create('jobs', function ($table) {
+ $table->integer('user_id')->unsigned();
+ $table->integer('location_id')->unsigned();
+ $table->integer('role_id')->unsigned();
+ $table->string('title');
+ });
+ }
+
+ /**
+ * Tear down the database schema.
+ *
+ * @return void
+ */
+ public function tearDown() {
+ $this->schema($this->schemaName)->drop('users');
+ $this->schema($this->schemaName)->drop('emails');
+ $this->schema($this->schemaName)->drop('phones');
+ $this->schema($this->schemaName)->drop('role_users');
+ $this->schema($this->schemaName)->drop('roles');
+ $this->schema($this->schemaName)->drop('permission_roles');
+ $this->schema($this->schemaName)->drop('permissions');
+ $this->schema($this->schemaName)->drop('tasks');
+ $this->schema($this->schemaName)->drop('locations');
+ $this->schema($this->schemaName)->drop('assignments');
+
+ Relation::morphMap([], FALSE);
+ }
+
+ /**
+ * Tests...
+ */
+ public function testOneToManyRelationship() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+ $user->emails()->create([
+ 'label' => 'primary',
+ 'email' => 'david@owlfancy.com'
+ ]);
+ $user->emails()->create([
+ 'label' => 'work',
+ 'email' => 'david@attenboroughsreef.com'
+ ]);
+
+ $emails = $user->emails;
+
+ $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $emails);
+ $this->assertEquals(2, $emails->count());
+ $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[0]);
+ $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[1]);
+ }
+
+ /**
+ * Tests our custom HasManySyncable class.
+ */
+ public function testSyncOneToMany() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+ // Set up original emails
+ $user->emails()->create([
+ 'id' => 1,
+ 'label' => 'primary',
+ 'email' => 'david@owlfancy.com'
+ ]);
+ $user->emails()->create([
+ 'id' => 2,
+ 'label' => 'work',
+ 'email' => 'david@attenboroughsreef.com'
+ ]);
+
+ // Delete `work`, update `primary`, and add `gmail`
+ $user->emails()->sync([
+ [
+ 'id' => 1,
+ 'email' => 'david@aol.com'
+ ],
+ [
+ 'label' => 'gmail',
+ 'email' => 'davidattenborough@gmail.com'
+ ]
+ ]);
+
+ $emails = $user->emails->toArray();
+
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'user_id' => 1,
+ 'label' => 'primary',
+ 'email' => 'david@aol.com'
+ ],
+ [
+ 'id' => 3,
+ 'user_id' => 1,
+ 'label' => 'gmail',
+ 'email' => 'davidattenborough@gmail.com'
+ ]
+ ], $emails);
+ }
+
+ /**
+ * Tests our custom MorphManySyncable class.
+ */
+ public function testSyncMorphMany() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+ // Set up original phones
+ $user->phones()->create([
+ 'id' => 1,
+ 'label' => 'primary',
+ 'number' => '5555551212'
+ ]);
+ $user->phones()->create([
+ 'id' => 2,
+ 'label' => 'work',
+ 'number' => '2223334444'
+ ]);
+
+ // Delete `work`, update `primary`, and add `fax`
+ $user->phones()->sync([
+ [
+ 'id' => 1,
+ 'number' => '8883332222'
+ ],
+ [
+ 'label' => 'fax',
+ 'number' => '5550005555'
+ ]
+ ]);
+
+ $phones = $user->phones->toArray();
+
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'phoneable_id' => 1,
+ 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser',
+ 'label' => 'primary',
+ 'number' => '8883332222'
+ ],
+ [
+ 'id' => 3,
+ 'phoneable_id' => 1,
+ 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser',
+ 'label' => 'fax',
+ 'number' => '5550005555'
+ ]
+ ], $phones);
+ }
+
+ public function testBelongsToManyUnique() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $this->generateLocations();
+ $this->generateRoles();
+ $this->generateJobs();
+
+ $expectedRoles = [
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 3
+ ]
+ ]
+ ];
+
+ $roles = $user->jobRoles;
+ $this->assertEquals($expectedRoles, $roles->toArray());
+
+ // Test eager loading
+ $users = EloquentTestUser::with('jobRoles')->get();
+ $this->assertEquals($expectedRoles, $users->toArray()[0]['job_roles']);
+ }
+
+ public function testMorphsToManyUnique() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+ $user2 = EloquentTestUser::create(['name' => 'Alex']);
+
+ $this->generateTasks();
+ $this->generateLocations();
+ $this->generateAssignments();
+
+ $expectedTasks = [
+ [
+ 'id' => 2,
+ 'name' => 'Chopping',
+ 'pivot' => [
+ 'assignable_id' => 1,
+ 'task_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'name' => 'Baleing',
+ 'pivot' => [
+ 'assignable_id' => 1,
+ 'task_id' => 3
+ ]
+ ]
+ ];
+
+ $tasks = $user->assignmentTasks;
+ $this->assertEquals($expectedTasks, $tasks->toArray());
+
+ // Test eager loading
+ $users = EloquentTestUser::with('assignmentTasks')->get();
+ $this->assertEquals($expectedTasks, $users->toArray()[0]['assignment_tasks']);
+ }
+
+ public function testMorphsToManyUniqueWithTertiary() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+ $user2 = EloquentTestUser::create(['name' => 'Alex']);
+
+ $this->generateTasks();
+ $this->generateLocations();
+ $this->generateAssignments();
+
+ $expectedTasks = [
+ [
+ 'id' => 2,
+ 'name' => 'Chopping',
+ 'pivot' => [
+ 'assignable_id' => 1,
+ 'task_id' => 2
+ ],
+ 'locations' => [
+ [
+ 'id' => 1,
+ 'name' => 'Hatchery',
+ 'pivot' => [
+ 'location_id' => 1,
+ 'task_id' => 2
+ ],
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'location_id' => 2,
+ 'task_id' => 2
+ ],
+ ]
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'name' => 'Baleing',
+ 'pivot' => [
+ 'assignable_id' => 1,
+ 'task_id' => 3
+ ],
+ 'locations' => [
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'location_id' => 2,
+ 'task_id' => 3
+ ],
+ ]
+ ]
+ ]
+ ];
+
+ $tasks = $user->tasks;
+ $this->assertEquals($expectedTasks, $tasks->toArray());
+
+ // Test eager loading
+ $users = EloquentTestUser::with('tasks')->get();
+ $this->assertEquals($expectedTasks, $users->toArray()[0]['tasks']);
+ }
+
+ public function testBelongsToManyUniqueWithTertiary() {
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $this->generateLocations();
+ $this->generateRoles();
+ $this->generateJobs();
+
+ $expectedJobs = [
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 2
+ ],
+ 'locations' => [
+ [
+ 'id' => 1,
+ 'name' => 'Hatchery',
+ 'pivot' => [
+ 'title' => 'Grunt',
+ 'location_id' => 1,
+ 'role_id' => 2
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'title' => 'Sergeant',
+ 'location_id' => 2,
+ 'role_id' => 2
+ ]
+ ]
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 3
+ ],
+ 'locations' => [
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'title' => 'Queen',
+ 'location_id' => 2,
+ 'role_id' => 3
+ ]
+ ]
+ ]
+ ]
+ ];
+
+ $jobs = $user->jobs()->withPivot('title')->get();
+ $this->assertEquals($expectedJobs, $jobs->toArray());
+
+ // Test eager loading
+ $users = EloquentTestUser::with(['jobs' => function ($relation) {
+ return $relation->withPivot('title');
+ }])->get();
+
+ $this->assertEquals($expectedJobs, $users->toArray()[0]['jobs']);
+ }
+
+ public function testBelongsToManyUniqueWithTertiaryEagerLoad() {
+ $user1 = EloquentTestUser::create(['name' => 'David']);
+ $user2 = EloquentTestUser::create(['name' => 'Alex']);
+
+ $this->generateLocations();
+ $this->generateRoles();
+ $this->generateJobs();
+
+ $users = EloquentTestUser::with('jobs')->get();
+
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'name' => 'David',
+ 'jobs' => [
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 2
+ ],
+ 'locations' => [
+ [
+ 'id' => 1,
+ 'name' => 'Hatchery',
+ 'pivot' => [
+ 'location_id' => 1,
+ 'role_id' => 2
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'location_id' => 2,
+ 'role_id' => 2
+ ]
+ ]
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 3
+ ],
+ 'locations' => [
+ [
+ 'id' => 2,
+ 'name' => 'Nexus',
+ 'pivot' => [
+ 'location_id' => 2,
+ 'role_id' => 3
+ ]
+ ]
+ ]
+ ]
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'Alex',
+ 'jobs' => [
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'user_id' => 2,
+ 'role_id' => 3
+ ],
+ 'locations' => [
+ [
+ 'id' => 1,
+ 'name' => 'Hatchery',
+ 'pivot' => [
+ 'location_id' => 1,
+ 'role_id' => 3
+ ]
+ ],
+ ]
+ ]
+ ]
+ ]
+ ], $users->toArray());
+ }
+
+ /**
+ * Test the ability of a BelongsToManyThrough relationship to retrieve structured data on a single model or set of models.
+ */
+ public function testBelongsToManyThrough() {
+ $this->generateRolesWithPermissions();
+
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $user->roles()->attach([1, 2]);
+
+ // Test retrieval of via models as well
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'slug' => 'uri_harvest',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 1
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'slug' => 'uri_spit_acid',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'uri_slash',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 3
+ ]
+ ]
+ ], $user->permissions->toArray());
+
+ // Test counting
+ $this->assertEquals(3, $user->permissions()->count());
+
+ $user2 = EloquentTestUser::create(['name' => 'Alex']);
+ $user2->roles()->attach([2, 3]);
+
+ // Test eager load
+ $users = EloquentTestUser::with('permissions')->get();
+ $usersWithPermissions = $users->toArray();
+
+ $this->assertEquals([
+ [
+ 'id' => 2,
+ 'slug' => 'uri_spit_acid',
+ 'pivot' => [
+ 'user_id' => 2,
+ 'permission_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'uri_slash',
+ 'pivot' => [
+ 'user_id' => 2,
+ 'permission_id' => 3
+ ]
+ ],
+ [
+ 'id' => 4,
+ 'slug' => 'uri_royal_jelly',
+ 'pivot' => [
+ 'user_id' => 2,
+ 'permission_id' => 4
+ ]
+ ]
+ ], $usersWithPermissions[1]['permissions']);
+
+ // Test counting related models (withCount)
+ $users = EloquentTestUser::withCount('permissions')->get();
+ $this->assertEquals(3, $users[0]->permissions_count);
+ $this->assertEquals(3, $users[1]->permissions_count);
+
+ $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[0]);
+ $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[1]);
+ $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[2]);
+ }
+
+ /**
+ * Test the ability of a BelongsToManyThrough relationship to retrieve and count paginated queries.
+ */
+ public function testBelongsToManyThroughPaginated() {
+ $this->generateRolesWithPermissions();
+
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $user->roles()->attach([1, 2]);
+
+ $paginatedPermissions = $user->permissions()->take(2)->offset(1);
+
+ $this->assertEquals([
+ [
+ 'id' => 2,
+ 'slug' => 'uri_spit_acid',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'uri_slash',
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 3
+ ]
+ ]
+ ], $paginatedPermissions->get()->toArray());
+
+ $this->assertEquals(2, $paginatedPermissions->count());
+ }
+
+ /**
+ * Test the ability of a BelongsToManyThrough relationship to retrieve structured data on a single model or set of models,
+ * eager loading the "via" models at the same time.
+ */
+ public function testBelongsToManyThroughWithVia() {
+ $this->generateRolesWithPermissions();
+
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $user->roles()->attach([1, 2]);
+
+ // Test retrieval of via models as well
+ $this->assertBelongsToManyThroughForDavid($user->permissions()->withVia('roles_via')->get()->toArray());
+
+ $user2 = EloquentTestUser::create(['name' => 'Alex']);
+ $user2->roles()->attach([2, 3]);
+
+ // Test eager loading
+ $users = EloquentTestUser::with(['permissions' => function ($query) {
+ return $query->withVia('roles_via');
+ }])->get();
+
+ $this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[0]);
+ $this->assertInstanceOf(EloquentTestRole::class, $users[0]->permissions[0]->roles_via[0]);
+
+ $usersWithPermissions = $users->toArray();
+
+ $this->assertBelongsToManyThroughForDavid($usersWithPermissions[0]['permissions']);
+ $this->assertBelongsToManyThroughForAlex($usersWithPermissions[1]['permissions']);
+ }
+
+ public function testQueryExclude() {
+ $this->generateRoles();
+ $this->generateJobs();
+ $job = EloquentTestJob::exclude('location_id', 'title')->first();
+
+ $this->assertEquals([
+ 'role_id' => 2,
+ 'user_id' => 1
+ ], $job->toArray());
+ }
+
+
+ public function testQueryExcludeOnJoinedTable() {
+ $this->generateRolesWithPermissions();
+
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $user->roles()->attach([1, 2]);
+
+ $users = EloquentTestUser::with(['permissions' => function ($query) {
+ $query->exclude('slug');
+ }])->get();
+
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'name' => 'David',
+ 'permissions' => [
+ [
+ 'id' => 1,
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 1
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'pivot' => [
+ 'user_id' => 1,
+ 'permission_id' => 3
+ ]
+ ]
+ ]
+ ]
+ ], $users->toArray());
+ }
+
+ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() {
+ $this->generateRolesWithPermissions();
+
+ $user = EloquentTestUser::create(['name' => 'David']);
+
+ $user->roles()->attach([1, 2]);
+
+ $users = EloquentTestUser::with(['roles' => function ($query) {
+ $query->addSelect('roles.*', 'jobs.*')->leftJoin('jobs', 'jobs.role_id', '=', 'roles.id')
+ ->exclude('slug', 'jobs.user_id', 'jobs.location_id', 'jobs.role_id');
+ }])->get();
+
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'name' => 'David',
+ 'roles' => [
+ [
+ 'id' => 1,
+ 'title' => NULL,
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 1
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'title' => NULL,
+ 'pivot' => [
+ 'user_id' => 1,
+ 'role_id' => 2
+ ]
+ ]
+ ]
+ ]
+ ], $users->toArray());
+ }
+
+ public function testQueryExcludeWildcard() {
+ $this->generateRoles();
+ $this->generateJobs();
+ $job = EloquentTestJob::select('*')->addSelect('user_id')->exclude('*')->first();
+
+ $this->assertEquals([
+ 'user_id' => 1
+ ], $job->toArray());
+
+ $job = EloquentTestJob::select('jobs.*')->addSelect('user_id')->exclude('*')->first();
+
+ $this->assertEquals([
+ 'user_id' => 1
+ ], $job->toArray());
+
+ $job = EloquentTestJob::select('*')->addSelect('user_id')->exclude('jobs.*')->first();
+
+ $this->assertEquals([
+ 'user_id' => 1
+ ], $job->toArray());
+ }
+
+ /**
+ * Helpers...
+ */
+
+ /**
+ * Get a database connection instance.
+ *
+ * @return \Illuminate\Database\Connection
+ */
+ protected function connection($connection = 'test_integration') {
+ return Model::getConnectionResolver()->connection($connection);
+ }
+
+ /**
+ * Get a schema builder instance.
+ *
+ * @return \Illuminate\Database\Schema\Builder
+ */
+ protected function schema($connection = 'test_integration') {
+ return $this->connection($connection)->getSchemaBuilder();
+ }
+
+ protected function generateRoles() {
+ return [
+ EloquentTestRole::create([
+ 'id' => 1,
+ 'slug' => 'forager'
+ ]),
+
+ EloquentTestRole::create([
+ 'id' => 2,
+ 'slug' => 'soldier'
+ ]),
+
+ EloquentTestRole::create([
+ 'id' => 3,
+ 'slug' => 'egg-layer'
+ ])
+ ];
+ }
+
+ protected function generatePermissions() {
+ return [
+ EloquentTestPermission::create([
+ 'id' => 1,
+ 'slug' => 'uri_harvest'
+ ]),
+
+ EloquentTestPermission::create([
+ 'id' => 2,
+ 'slug' => 'uri_spit_acid'
+ ]),
+
+ EloquentTestPermission::create([
+ 'id' => 3,
+ 'slug' => 'uri_slash'
+ ]),
+
+ EloquentTestPermission::create([
+ 'id' => 4,
+ 'slug' => 'uri_royal_jelly'
+ ])
+ ];
+ }
+
+ protected function generateRolesWithPermissions() {
+ $roles = $this->generateRoles();
+
+ $this->generatePermissions();
+
+ $roles[0]->permissions()->attach([1, 2]);
+ // We purposefully want a permission that belongs to more than one role
+ $roles[1]->permissions()->attach([2, 3]);
+ $roles[2]->permissions()->attach([2, 4]);
+
+ return $roles;
+ }
+
+ protected function generateJobs() {
+
+ /**
+ * Sample data
+ *
+ * | user_id | role_id | location_id |
+ * |---------|---------|-------------|
+ * | 1 | 2 | 1 |
+ * | 1 | 2 | 2 |
+ * | 1 | 3 | 2 |
+ * | 2 | 3 | 1 |
+ */
+
+ return [
+ EloquentTestJob::create([
+ 'role_id' => 2,
+ 'location_id' => 1,
+ 'user_id' => 1,
+ 'title' => 'Grunt'
+ ]),
+ EloquentTestJob::create([
+ 'role_id' => 2,
+ 'location_id' => 2,
+ 'user_id' => 1,
+ 'title' => 'Sergeant'
+ ]),
+ EloquentTestJob::create([
+ 'role_id' => 3,
+ 'location_id' => 2,
+ 'user_id' => 1,
+ 'title' => 'Queen'
+ ]),
+ EloquentTestJob::create([
+ 'role_id' => 3,
+ 'location_id' => 1,
+ 'user_id' => 2,
+ 'title' => 'Demi-queen'
+ ])
+ ];
+ }
+
+ protected function generateLocations() {
+ return [
+ EloquentTestLocation::create([
+ 'id' => 1,
+ 'name' => 'Hatchery'
+ ]),
+
+ EloquentTestLocation::create([
+ 'id' => 2,
+ 'name' => 'Nexus'
+ ])
+ ];
+ }
+
+ protected function generateTasks() {
+ return [
+ EloquentTestTask::create([
+ 'id' => 1,
+ 'name' => 'Digging'
+ ]),
+
+ EloquentTestTask::create([
+ 'id' => 2,
+ 'name' => 'Chopping'
+ ]),
+
+ EloquentTestTask::create([
+ 'id' => 3,
+ 'name' => 'Baleing'
+ ])
+ ];
+ }
+
+ protected function generateAssignments() {
+ return [
+ EloquentTestAssignment::create([
+ 'task_id' => 2,
+ 'location_id' => 1,
+ 'assignable_id' => 1,
+ 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser'
+ ]),
+ EloquentTestAssignment::create([
+ 'task_id' => 2,
+ 'location_id' => 2,
+ 'assignable_id' => 1,
+ 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser'
+ ]),
+ EloquentTestAssignment::create([
+ 'task_id' => 3,
+ 'location_id' => 2,
+ 'assignable_id' => 1,
+ 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser'
+ ]),
+ EloquentTestAssignment::create([
+ 'task_id' => 3,
+ 'location_id' => 3,
+ 'assignable_id' => 1,
+ 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestNonExistant'
+ ]),
+ EloquentTestAssignment::create([
+ 'task_id' => 3,
+ 'location_id' => 1,
+ 'assignable_id' => 2,
+ 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser'
+ ])
+ ];
+ }
+
+ protected function assertBelongsToManyThroughForDavid($permissions) {
+ // User should have effective permissions uri_harvest, uri_spit_acid, and uri_slash.
+ // We also check that the 'roles_via' relationship is properly set.
+ $this->assertEquals('uri_harvest', $permissions[0]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'slug' => 'forager',
+ 'pivot' => [
+ 'permission_id' => 1,
+ 'role_id' => 1
+ ]
+ ]
+ ], $permissions[0]['roles_via']);
+ $this->assertEquals('uri_spit_acid', $permissions[1]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 1,
+ 'slug' => 'forager',
+ 'pivot' => [
+ 'permission_id' => 2,
+ 'role_id' => 1
+ ]
+ ],
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'permission_id' => 2,
+ 'role_id' => 2
+ ]
+ ]
+ ], $permissions[1]['roles_via']);
+ $this->assertEquals('uri_slash', $permissions[2]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'permission_id' => 3,
+ 'role_id' => 2
+ ]
+ ]
+ ], $permissions[2]['roles_via']);
+ }
+
+ protected function assertBelongsToManyThroughForAlex($permissions) {
+ // User should have effective permissions uri_spit_acid, uri_slash, and uri_royal_jelly.
+ // We also check that the 'roles_via' relationship is properly set.
+ $this->assertEquals('uri_spit_acid', $permissions[0]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'permission_id' => 2,
+ 'role_id' => 2
+ ]
+ ],
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'permission_id' => 2,
+ 'role_id' => 3
+ ]
+ ]
+ ], $permissions[0]['roles_via']);
+ $this->assertEquals('uri_slash', $permissions[1]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 2,
+ 'slug' => 'soldier',
+ 'pivot' => [
+ 'permission_id' => 3,
+ 'role_id' => 2
+ ]
+ ]
+ ], $permissions[1]['roles_via']);
+ $this->assertEquals('uri_royal_jelly', $permissions[2]['slug']);
+ $this->assertEquals([
+ [
+ 'id' => 3,
+ 'slug' => 'egg-layer',
+ 'pivot' => [
+ 'permission_id' => 4,
+ 'role_id' => 3
+ ]
+ ]
+ ], $permissions[2]['roles_via']);
+ }
+}
+
+/**
+ * Eloquent Models...
+ */
+class EloquentTestModel extends Model
+{
+ protected $connection = 'test_integration';
+}
+
+class EloquentTestUser extends EloquentTestModel
+{
+ protected $table = 'users';
+ protected $guarded = [];
+
+ public function emails() {
+ return $this->hasMany('UserFrosting\Tests\Integration\EloquentTestEmail', 'user_id');
+ }
+
+ public function phones() {
+ return $this->morphMany('UserFrosting\Tests\Integration\EloquentTestPhone', 'phoneable');
+ }
+
+ /**
+ * Get all roles to which this user belongs.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
+ */
+ public function roles() {
+ return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'role_users', 'user_id', 'role_id');
+ }
+
+ /**
+ * Get all of the permissions this user has, via its roles.
+ *
+ * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough
+ */
+ public function permissions() {
+ return $this->belongsToManyThrough(
+ 'UserFrosting\Tests\Integration\EloquentTestPermission',
+ 'UserFrosting\Tests\Integration\EloquentTestRole',
+ 'role_users',
+ 'user_id',
+ 'role_id',
+ 'permission_roles',
+ 'role_id',
+ 'permission_id'
+ );
+ }
+
+ /**
+ * Get all of the user's unique tasks.
+ */
+ public function assignmentTasks() {
+ $relation = $this->morphToManyUnique(
+ 'UserFrosting\Tests\Integration\EloquentTestTask',
+ 'assignable',
+ 'assignments',
+ NULL,
+ 'task_id' // Need to explicitly set this, since it doesn't match our related model name
+ );
+
+ return $relation;
+ }
+
+ /**
+ * Get all of the user's unique tasks along with the task locations.
+ */
+ public function tasks() {
+ $relation = $this->morphToManyUnique(
+ 'UserFrosting\Tests\Integration\EloquentTestTask',
+ 'assignable',
+ 'assignments',
+ NULL,
+ 'task_id' // Need to explicitly set this, since it doesn't match our related model name
+ )->withTertiary(EloquentTestLocation::class, NULL, 'location_id');
+
+ return $relation;
+ }
+
+ /**
+ * Get all of the user's unique roles based on their jobs.
+ */
+ public function jobRoles() {
+ $relation = $this->belongsToManyUnique(
+ 'UserFrosting\Tests\Integration\EloquentTestRole',
+ 'jobs',
+ 'user_id',
+ 'role_id'
+ );
+
+ return $relation;
+ }
+
+ /**
+ * Get all of the user's unique roles based on their jobs as a tertiary relationship.
+ */
+ public function jobs() {
+ $relation = $this->belongsToManyUnique(
+ EloquentTestRole::class,
+ 'jobs',
+ 'user_id',
+ 'role_id'
+ )->withTertiary(EloquentTestLocation::class, NULL, 'location_id');
+
+ return $relation;
+ }
+}
+
+class EloquentTestEmail extends EloquentTestModel
+{
+ protected $table = 'emails';
+ protected $guarded = [];
+
+ public function user() {
+ return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestUser', 'user_id');
+ }
+}
+
+class EloquentTestPhone extends EloquentTestModel
+{
+ protected $table = 'phones';
+ protected $guarded = [];
+
+ public function phoneable() {
+ return $this->morphTo();
+ }
+}
+
+class EloquentTestRole extends EloquentTestModel
+{
+ protected $table = 'roles';
+ protected $guarded = [];
+
+ /**
+ * Get a list of permissions assigned to this role.
+ */
+ public function permissions() {
+ return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestPermission', 'permission_roles', 'role_id', 'permission_id');
+ }
+}
+
+class EloquentTestPermission extends EloquentTestModel
+{
+ protected $table = 'permissions';
+ protected $guarded = [];
+
+ /**
+ * Get a list of roles that have this permission.
+ */
+ public function roles() {
+ return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'permission_roles', 'permission_id', 'role_id');
+ }
+}
+
+class EloquentTestTask extends EloquentTestModel
+{
+ protected $table = 'tasks';
+ protected $guarded = [];
+
+ public function locations() {
+ return $this->belongsToMany(
+ 'UserFrosting\Tests\Integration\EloquentTestLocation',
+ 'assignments',
+ 'task_id',
+ 'location_id'
+ );
+ }
+}
+
+class EloquentTestLocation extends EloquentTestModel
+{
+ protected $table = 'locations';
+ protected $guarded = [];
+}
+
+class EloquentTestAssignment extends EloquentTestModel
+{
+ protected $table = 'assignments';
+ protected $guarded = [];
+
+ /**
+ * Get all of the users that are assigned to this assignment.
+ */
+ public function users() {
+ return $this->morphedByMany('UserFrosting\Tests\Integration\EloquentTestUser', 'assignable');
+ }
+}
+
+class EloquentTestJob extends EloquentTestModel
+{
+ protected $table = 'jobs';
+ protected $guarded = [];
+
+ /**
+ * Get the role for this job.
+ */
+ public function role() {
+ return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestRole', 'role_id');
+ }
+}
diff --git a/main/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/main/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index 04d3843..81ef642 100644 --- a/main/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/main/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -1,101 +1,101 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Tests\Unit; - -use Illuminate\Database\Capsule\Manager as DB; -use Illuminate\Database\Eloquent\Builder as EloquentBuilder; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; -use Mockery as m; -use ReflectionClass; -use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; -use UserFrosting\Sprinkle\Core\Database\Builder as QueryBuilder; -use UserFrosting\Sprinkle\Core\Database\Models\Model; -use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough; - -/** - * Tests the BelongsToManyThrough relation. - * - * @extends TestCase - */ -class BelongsToManyThroughTest extends TestCase -{ - public function tearDown() { - m::close(); - } - - function testPaginatedQuery() { - // Creates a real BelongsToManyThrough object - $relation = $this->getRelation(); - - // We need to define a mock base query, because Eloquent\Builder will pass through many calls - // to this underlying Query\Builder object. - $baseQuery = m::mock(QueryBuilder::class); - $builder = m::mock(EloquentBuilder::class, [$baseQuery])->makePartial(); - - $related = $relation->getRelated(); - $related->shouldReceive('getQualifiedKeyName')->once()->andReturn('users.id'); - - $builder->shouldReceive('withGlobalScope')->once()->andReturnSelf(); - - $builder->shouldReceive('limit')->once()->with(2)->andReturnSelf(); - $builder->shouldReceive('offset')->once()->with(1)->andReturnSelf(); - - // Mock the collection generated by the constrained query - $collection = m::mock('Illuminate\Database\Eloquent\Collection'); - $collection->shouldReceive('pluck')->once()->with('id')->andReturn($collection); - $collection->shouldReceive('toArray')->once()->andReturn([1, 2]); - $builder->shouldReceive('get')->once()->andReturn($collection); - - // Test the final modification to the original unpaginated query - $builder->shouldReceive('whereIn')->once()->with('users.id', [1, 2])->andReturnSelf(); - - $paginatedQuery = $relation->getPaginatedQuery($builder, 2, 1); - } - - /** - * Set up and simulate base expectations for arguments to relationship. - */ - protected function getRelation() { - // We simulate a BelongsToManyThrough relationship that gets all related users for a specified permission(s). - $builder = m::mock(EloquentBuilder::class); - $related = m::mock('Illuminate\Database\Eloquent\Model'); - $related->shouldReceive('getKey')->andReturn(1); - $related->shouldReceive('getTable')->andReturn('users'); - $related->shouldReceive('getKeyName')->andReturn('id'); - // Tie the mocked builder to the mocked related model - $builder->shouldReceive('getModel')->andReturn($related); - - // Mock the intermediate role->permission BelongsToMany relation - $intermediateRelationship = m::mock(BelongsToMany::class); - $intermediateRelationship->shouldReceive('getTable')->once()->andReturn('permission_roles'); - $intermediateRelationship->shouldReceive('getQualifiedRelatedKeyName')->once()->andReturn('permission_roles.role_id'); - // Crazy pivot query stuff - $newPivot = m::mock('\Illuminate\Database\Eloquent\Relations\Pivot'); - $newPivot->shouldReceive('getForeignKey')->andReturn('permission_id'); - $intermediateRelationship->shouldReceive('newExistingPivot')->andReturn($newPivot); - - // Expectations for joining the main relation - users to roles - $builder->shouldReceive('join')->once()->with('role_users', 'users.id', '=', 'role_users.user_id'); - - // Expectations for joining the intermediate relation - roles to permissions - $builder->shouldReceive('join')->once()->with('permission_roles', 'permission_roles.role_id', '=', 'role_users.role_id'); - $builder->shouldReceive('where')->once()->with('permission_id', '=', 1); - - // Now we set up the relationship with the related model. - return new BelongsToManyThrough( - $builder, $related, $intermediateRelationship, 'role_users', 'role_id', 'user_id', 'relation_name' - ); - } -} - -class EloquentBelongsToManyModelStub extends Model -{ - protected $guarded = []; -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Tests\Unit;
+
+use Illuminate\Database\Capsule\Manager as DB;
+use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+use Mockery as m;
+use ReflectionClass;
+use UserFrosting\Tests\TestCase;
+use UserFrosting\Tests\DatabaseTransactions;
+use UserFrosting\Sprinkle\Core\Database\Builder as QueryBuilder;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough;
+
+/**
+ * Tests the BelongsToManyThrough relation.
+ *
+ * @extends TestCase
+ */
+class BelongsToManyThroughTest extends TestCase
+{
+ public function tearDown() {
+ m::close();
+ }
+
+ function testPaginatedQuery() {
+ // Creates a real BelongsToManyThrough object
+ $relation = $this->getRelation();
+
+ // We need to define a mock base query, because Eloquent\Builder will pass through many calls
+ // to this underlying Query\Builder object.
+ $baseQuery = m::mock(QueryBuilder::class);
+ $builder = m::mock(EloquentBuilder::class, [$baseQuery])->makePartial();
+
+ $related = $relation->getRelated();
+ $related->shouldReceive('getQualifiedKeyName')->once()->andReturn('users.id');
+
+ $builder->shouldReceive('withGlobalScope')->once()->andReturnSelf();
+
+ $builder->shouldReceive('limit')->once()->with(2)->andReturnSelf();
+ $builder->shouldReceive('offset')->once()->with(1)->andReturnSelf();
+
+ // Mock the collection generated by the constrained query
+ $collection = m::mock('Illuminate\Database\Eloquent\Collection');
+ $collection->shouldReceive('pluck')->once()->with('id')->andReturn($collection);
+ $collection->shouldReceive('toArray')->once()->andReturn([1, 2]);
+ $builder->shouldReceive('get')->once()->andReturn($collection);
+
+ // Test the final modification to the original unpaginated query
+ $builder->shouldReceive('whereIn')->once()->with('users.id', [1, 2])->andReturnSelf();
+
+ $paginatedQuery = $relation->getPaginatedQuery($builder, 2, 1);
+ }
+
+ /**
+ * Set up and simulate base expectations for arguments to relationship.
+ */
+ protected function getRelation() {
+ // We simulate a BelongsToManyThrough relationship that gets all related users for a specified permission(s).
+ $builder = m::mock(EloquentBuilder::class);
+ $related = m::mock('Illuminate\Database\Eloquent\Model');
+ $related->shouldReceive('getKey')->andReturn(1);
+ $related->shouldReceive('getTable')->andReturn('users');
+ $related->shouldReceive('getKeyName')->andReturn('id');
+ // Tie the mocked builder to the mocked related model
+ $builder->shouldReceive('getModel')->andReturn($related);
+
+ // Mock the intermediate role->permission BelongsToMany relation
+ $intermediateRelationship = m::mock(BelongsToMany::class);
+ $intermediateRelationship->shouldReceive('getTable')->once()->andReturn('permission_roles');
+ $intermediateRelationship->shouldReceive('getQualifiedRelatedKeyName')->once()->andReturn('permission_roles.role_id');
+ // Crazy pivot query stuff
+ $newPivot = m::mock('\Illuminate\Database\Eloquent\Relations\Pivot');
+ $newPivot->shouldReceive('getForeignKey')->andReturn('permission_id');
+ $intermediateRelationship->shouldReceive('newExistingPivot')->andReturn($newPivot);
+
+ // Expectations for joining the main relation - users to roles
+ $builder->shouldReceive('join')->once()->with('role_users', 'users.id', '=', 'role_users.user_id');
+
+ // Expectations for joining the intermediate relation - roles to permissions
+ $builder->shouldReceive('join')->once()->with('permission_roles', 'permission_roles.role_id', '=', 'role_users.role_id');
+ $builder->shouldReceive('where')->once()->with('permission_id', '=', 1);
+
+ // Now we set up the relationship with the related model.
+ return new BelongsToManyThrough(
+ $builder, $related, $intermediateRelationship, 'role_users', 'role_id', 'user_id', 'relation_name'
+ );
+ }
+}
+
+class EloquentBelongsToManyModelStub extends Model
+{
+ protected $guarded = [];
+}
diff --git a/main/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/main/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php index d53976a..f94fbd5 100644 --- a/main/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php +++ b/main/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -1,114 +1,114 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Tests\Unit; - -use stdClass; -use Mockery as m; -use ReflectionClass; -use PHPUnit\Framework\TestCase; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Collection as BaseCollection; -use Illuminate\Database\Eloquent\ModelNotFoundException; - -use UserFrosting\Sprinkle\Core\Database\Relations\HasManySyncable; - -class DatabaseSyncableTest extends TestCase -{ - public function tearDown() { - m::close(); - } - - /** - * @dataProvider syncMethodHasManyListProvider - */ - public function testSyncMethod($list) { - $relation = $this->getRelation(); - - // Simulate determination of related key from builder - $relation->getRelated()->shouldReceive('getKeyName')->once()->andReturn('id'); - - // Simulate fetching of current relationships (1,2,3) - $query = m::mock('stdClass'); - $relation->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('id')->andReturn(new BaseCollection([1, 2, 3])); - - // withoutGlobalScopes will get called exactly 3 times - $relation->getRelated()->shouldReceive('withoutGlobalScopes')->times(3)->andReturn($query); - - // Test deletions of items removed from relationship (1) - $query->shouldReceive('whereIn')->once()->with('id', [1])->andReturn($query); - $query->shouldReceive('delete')->once()->andReturn($query); - - // Test updates to existing items in relationship (2,3) - $query->shouldReceive('where')->once()->with('id', 2)->andReturn($query); - $query->shouldReceive('update')->once()->with(['id' => 2, 'species' => 'Tyto'])->andReturn($query); - $query->shouldReceive('where')->once()->with('id', 3)->andReturn($query); - $query->shouldReceive('update')->once()->with(['id' => 3, 'species' => 'Megascops'])->andReturn($query); - - // Test creation of new items ('x') - $model = $this->expectCreatedModel($relation, [ - 'id' => 'x' - ]); - $model->shouldReceive('getAttribute')->with('id')->andReturn('x'); - - $this->assertEquals(['created' => ['x'], 'deleted' => [1], 'updated' => [2, 3]], $relation->sync($list)); - } - - /** - * Set up and simulate base expectations for arguments to relationship. - */ - protected function getRelation() { - $builder = m::mock('Illuminate\Database\Eloquent\Builder'); - $builder->shouldReceive('whereNotNull')->with('table.foreign_key'); - $builder->shouldReceive('where')->with('table.foreign_key', '=', 1); - $related = m::mock('Illuminate\Database\Eloquent\Model'); - $builder->shouldReceive('getModel')->andReturn($related); - $parent = m::mock('Illuminate\Database\Eloquent\Model'); - $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); - $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); - $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); - return new HasManySyncable($builder, $parent, 'table.foreign_key', 'id'); - } - - public function syncMethodHasManyListProvider() { - return [ - // First test set - [ - // First argument - [ - [ - 'id' => 2, - 'species' => 'Tyto' - ], - [ - 'id' => 3, - 'species' => 'Megascops' - ], - [ - 'id' => 'x' - ] - ] - ] - // Additional test sets here - ]; - } - - protected function expectNewModel($relation, $attributes = NULL) { - $relation->getRelated()->shouldReceive('newInstance')->once()->with($attributes)->andReturn($model = m::mock(Model::class)); - $model->shouldReceive('setAttribute')->with('foreign_key', 1)->andReturn($model); - return $model; - } - - protected function expectCreatedModel($relation, $attributes) { - $model = $this->expectNewModel($relation, $attributes); - $model->shouldReceive('save')->andReturn($model); - return $model; - } -} +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Tests\Unit;
+
+use stdClass;
+use Mockery as m;
+use ReflectionClass;
+use PHPUnit\Framework\TestCase;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Collection as BaseCollection;
+use Illuminate\Database\Eloquent\ModelNotFoundException;
+
+use UserFrosting\Sprinkle\Core\Database\Relations\HasManySyncable;
+
+class DatabaseSyncableTest extends TestCase
+{
+ public function tearDown() {
+ m::close();
+ }
+
+ /**
+ * @dataProvider syncMethodHasManyListProvider
+ */
+ public function testSyncMethod($list) {
+ $relation = $this->getRelation();
+
+ // Simulate determination of related key from builder
+ $relation->getRelated()->shouldReceive('getKeyName')->once()->andReturn('id');
+
+ // Simulate fetching of current relationships (1,2,3)
+ $query = m::mock('stdClass');
+ $relation->shouldReceive('newQuery')->once()->andReturn($query);
+ $query->shouldReceive('pluck')->once()->with('id')->andReturn(new BaseCollection([1, 2, 3]));
+
+ // withoutGlobalScopes will get called exactly 3 times
+ $relation->getRelated()->shouldReceive('withoutGlobalScopes')->times(3)->andReturn($query);
+
+ // Test deletions of items removed from relationship (1)
+ $query->shouldReceive('whereIn')->once()->with('id', [1])->andReturn($query);
+ $query->shouldReceive('delete')->once()->andReturn($query);
+
+ // Test updates to existing items in relationship (2,3)
+ $query->shouldReceive('where')->once()->with('id', 2)->andReturn($query);
+ $query->shouldReceive('update')->once()->with(['id' => 2, 'species' => 'Tyto'])->andReturn($query);
+ $query->shouldReceive('where')->once()->with('id', 3)->andReturn($query);
+ $query->shouldReceive('update')->once()->with(['id' => 3, 'species' => 'Megascops'])->andReturn($query);
+
+ // Test creation of new items ('x')
+ $model = $this->expectCreatedModel($relation, [
+ 'id' => 'x'
+ ]);
+ $model->shouldReceive('getAttribute')->with('id')->andReturn('x');
+
+ $this->assertEquals(['created' => ['x'], 'deleted' => [1], 'updated' => [2, 3]], $relation->sync($list));
+ }
+
+ /**
+ * Set up and simulate base expectations for arguments to relationship.
+ */
+ protected function getRelation() {
+ $builder = m::mock('Illuminate\Database\Eloquent\Builder');
+ $builder->shouldReceive('whereNotNull')->with('table.foreign_key');
+ $builder->shouldReceive('where')->with('table.foreign_key', '=', 1);
+ $related = m::mock('Illuminate\Database\Eloquent\Model');
+ $builder->shouldReceive('getModel')->andReturn($related);
+ $parent = m::mock('Illuminate\Database\Eloquent\Model');
+ $parent->shouldReceive('getAttribute')->with('id')->andReturn(1);
+ $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at');
+ $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at');
+ return new HasManySyncable($builder, $parent, 'table.foreign_key', 'id');
+ }
+
+ public function syncMethodHasManyListProvider() {
+ return [
+ // First test set
+ [
+ // First argument
+ [
+ [
+ 'id' => 2,
+ 'species' => 'Tyto'
+ ],
+ [
+ 'id' => 3,
+ 'species' => 'Megascops'
+ ],
+ [
+ 'id' => 'x'
+ ]
+ ]
+ ]
+ // Additional test sets here
+ ];
+ }
+
+ protected function expectNewModel($relation, $attributes = NULL) {
+ $relation->getRelated()->shouldReceive('newInstance')->once()->with($attributes)->andReturn($model = m::mock(Model::class));
+ $model->shouldReceive('setAttribute')->with('foreign_key', 1)->andReturn($model);
+ return $model;
+ }
+
+ protected function expectCreatedModel($relation, $attributes) {
+ $model = $this->expectNewModel($relation, $attributes);
+ $model->shouldReceive('save')->andReturn($model);
+ return $model;
+ }
+}
diff --git a/main/app/sprinkles/core/tests/Unit/SprunjeTest.php b/main/app/sprinkles/core/tests/Unit/SprunjeTest.php index dab34a5..66fcb34 100644 --- a/main/app/sprinkles/core/tests/Unit/SprunjeTest.php +++ b/main/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -1,96 +1,96 @@ -<?php -/** - * UserFrosting (http://www.userfrosting.com) - * - * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - */ - -namespace UserFrosting\Tests\Unit; - -use Illuminate\Database\Capsule\Manager as DB; -use Mockery as m; -use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; -use UserFrosting\Sprinkle\Core\Database\Builder as Builder; -use UserFrosting\Sprinkle\Core\Database\Models\Model; -use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; -use UserFrosting\Sprinkle\Core\Util\ClassMapper; - -/** - * SprunjeTest class. - * Tests a basic Sprunje. - * - * @extends TestCase - */ -class SprunjeTest extends TestCase -{ - public function tearDown() { - m::close(); - } - - function testSprunjeApplyFiltersDefault() { - $sprunje = new SprunjeStub([ - 'filters' => [ - 'species' => 'Tyto' - ] - ]); - - $builder = $sprunje->getQuery(); - - // Need to mock the new Builder instance that Laravel spawns in the where() closure. - // See https://stackoverflow.com/questions/20701679/mocking-callbacks-in-laravel-4-mockery - $builder->shouldReceive('newQuery')->andReturn( - $subBuilder = m::mock(Builder::class, function ($subQuery) { - $subQuery->makePartial(); - $subQuery->shouldReceive('orLike')->with('species', 'Tyto')->once()->andReturn($subQuery); - }) - ); - - $sprunje->applyFilters($builder); - } - - function testSprunjeApplySortsDefault() { - $sprunje = new SprunjeStub([ - 'sorts' => [ - 'species' => 'asc' - ] - ]); - - $builder = $sprunje->getQuery(); - $builder->shouldReceive('orderBy')->once()->with('species', 'asc'); - $sprunje->applySorts($builder); - } - -} - -class SprunjeStub extends Sprunje -{ - protected $filterable = [ - 'species' - ]; - - protected $sortable = [ - 'species' - ]; - - public function __construct($options) { - $classMapper = new ClassMapper(); - parent::__construct($classMapper, $options); - } - - protected function baseQuery() { - // We use a partial mock for Builder, because we need to be able to run some of its actual methods. - // For example, we need to be able to run the `where` method with a closure. - $builder = m::mock(Builder::class); - $builder->makePartial(); - - return $builder; - } -} - -class SprunjeTestModelStub extends Model -{ - protected $table = 'table'; -} - +<?php
+/**
+ * UserFrosting (http://www.userfrosting.com)
+ *
+ * @link https://github.com/userfrosting/UserFrosting
+ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
+ */
+
+namespace UserFrosting\Tests\Unit;
+
+use Illuminate\Database\Capsule\Manager as DB;
+use Mockery as m;
+use UserFrosting\Tests\TestCase;
+use UserFrosting\Tests\DatabaseTransactions;
+use UserFrosting\Sprinkle\Core\Database\Builder as Builder;
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+use UserFrosting\Sprinkle\Core\Sprunje\Sprunje;
+use UserFrosting\Sprinkle\Core\Util\ClassMapper;
+
+/**
+ * SprunjeTest class.
+ * Tests a basic Sprunje.
+ *
+ * @extends TestCase
+ */
+class SprunjeTest extends TestCase
+{
+ public function tearDown() {
+ m::close();
+ }
+
+ function testSprunjeApplyFiltersDefault() {
+ $sprunje = new SprunjeStub([
+ 'filters' => [
+ 'species' => 'Tyto'
+ ]
+ ]);
+
+ $builder = $sprunje->getQuery();
+
+ // Need to mock the new Builder instance that Laravel spawns in the where() closure.
+ // See https://stackoverflow.com/questions/20701679/mocking-callbacks-in-laravel-4-mockery
+ $builder->shouldReceive('newQuery')->andReturn(
+ $subBuilder = m::mock(Builder::class, function ($subQuery) {
+ $subQuery->makePartial();
+ $subQuery->shouldReceive('orLike')->with('species', 'Tyto')->once()->andReturn($subQuery);
+ })
+ );
+
+ $sprunje->applyFilters($builder);
+ }
+
+ function testSprunjeApplySortsDefault() {
+ $sprunje = new SprunjeStub([
+ 'sorts' => [
+ 'species' => 'asc'
+ ]
+ ]);
+
+ $builder = $sprunje->getQuery();
+ $builder->shouldReceive('orderBy')->once()->with('species', 'asc');
+ $sprunje->applySorts($builder);
+ }
+
+}
+
+class SprunjeStub extends Sprunje
+{
+ protected $filterable = [
+ 'species'
+ ];
+
+ protected $sortable = [
+ 'species'
+ ];
+
+ public function __construct($options) {
+ $classMapper = new ClassMapper();
+ parent::__construct($classMapper, $options);
+ }
+
+ protected function baseQuery() {
+ // We use a partial mock for Builder, because we need to be able to run some of its actual methods.
+ // For example, we need to be able to run the `where` method with a closure.
+ $builder = m::mock(Builder::class);
+ $builder->makePartial();
+
+ return $builder;
+ }
+}
+
+class SprunjeTestModelStub extends Model
+{
+ protected $table = 'table';
+}
+
|