diff options
Diffstat (limited to 'login/app/sprinkles/core/tests')
4 files changed, 1637 insertions, 0 deletions
diff --git a/login/app/sprinkles/core/tests/Integration/DatabaseTests.php b/login/app/sprinkles/core/tests/Integration/DatabaseTests.php new file mode 100755 index 0000000..231bb86 --- /dev/null +++ b/login/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -0,0 +1,1315 @@ +<?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/login/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/login/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php new file mode 100755 index 0000000..d4fd4f8 --- /dev/null +++ b/login/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -0,0 +1,103 @@ +<?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/login/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/login/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php new file mode 100755 index 0000000..188b012 --- /dev/null +++ b/login/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -0,0 +1,119 @@ +<?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/login/app/sprinkles/core/tests/Unit/SprunjeTest.php b/login/app/sprinkles/core/tests/Unit/SprunjeTest.php new file mode 100755 index 0000000..fa19319 --- /dev/null +++ b/login/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -0,0 +1,100 @@ +<?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'; +} + |