Skip to content

Commit

Permalink
feat(Testing): Add AssertProviderPolicies for testing policies
Browse files Browse the repository at this point in the history
  • Loading branch information
pionl committed Jul 24, 2023
1 parent 55c4727 commit 1d55e84
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 2 deletions.
86 changes: 86 additions & 0 deletions src/Testing/Providers/Concerns/AssertProviderPolicies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

declare(strict_types=1);

namespace LaraStrict\Testing\Providers\Concerns;

use Illuminate\Contracts\Auth\Access\Gate;
use Illuminate\Contracts\Foundation\Application;
use PHPUnit\Framework\Assert;
use ReflectionClass;

trait AssertProviderPolicies
{
/**
* @param array<string, class-string<object>> $policyMap
*/
protected function assertPolicies(Application $application, array $policyMap): void
{
$gate = $application->get(Gate::class);
assert($gate instanceof Gate);

foreach ($policyMap as $key => $expectedClass) {
$this->getPolicy(gate: $gate, policy: $key, expectedPolicyClass: $expectedClass);
}
}

/**
* @template T of object
* @param class-string<T> $expectedPolicyClass
*
* @return T
*/
protected function assertPolicy(
Application $application,
string $policy,
string $expectedPolicyClass,
string|bool|null $expectToExtendClass = false
): object {
$gate = $application->get(Gate::class);
assert($gate instanceof Gate);

$policyInstance = $this->getPolicy($gate, $policy, $expectedPolicyClass);

if (is_bool($expectToExtendClass)) {
return $policyInstance;
}

$reflection = new ReflectionClass($policyInstance);
$parentClass = $reflection->getParentClass();

if ($expectToExtendClass === null) {
Assert::assertTrue(
condition: $parentClass === false,
message: sprintf('Policy (%s) does should not extend any class', $policy)
);
return $policyInstance;
}

Assert::assertTrue(condition: $parentClass !== false, message: 'Policy does not extend any class');
Assert::assertEquals(
expected: $expectToExtendClass,
actual: $parentClass->getName(),
message: sprintf('Policy (%s)does not extend expected class', $policy)
);

return $policyInstance;
}

/**
* @template TIn of object
* @param class-string<TIn> $expectedPolicyClass
*
* @return TIn
*/
private function getPolicy(Gate $gate, string $policy, string $expectedPolicyClass): object
{
$policy = $gate->getPolicyFor($policy);
Assert::assertInstanceOf(
expected: $expectedPolicyClass,
actual: $policy,
message: 'Policy does not match expected class'
);

return $policy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Tests\LaraStrict\Feature\Testing\Providers\Concerns;

use LaraStrict\Testing\Providers\Concerns\AssertProviderPolicies;
use Tests\LaraStrict\Feature\TestCase;

class AssertProviderPoliciesTest extends TestCase
{
use AssertProviderPolicies;

protected function setUp(): void
{
parent::setUp();

$this->app()
->register(ProviderPolicyServiceProvider::class);
}

public function testAssertPolicies(): void
{
$this->assertPolicies($this->app(), [
TestPolicy::class => TestPolicy::class,
MyOtherPolicyContract::class => MyOtherPolicy::class,
]);
}

public function testAssertPolicyWithExtendCheck(): void
{
$this->assertPolicy(
application: $this->app(),
policy: TestPolicy::class,
expectedPolicyClass: TestPolicy::class,
expectToExtendClass: MyOtherPolicy::class
);
$this->assertPolicy(
application: $this->app(),
policy: MyOtherPolicyContract::class,
expectedPolicyClass: MyOtherPolicy::class,
expectToExtendClass: null
);
}
}
13 changes: 13 additions & 0 deletions tests/Feature/Testing/Providers/Concerns/MyOtherPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Tests\LaraStrict\Feature\Testing\Providers\Concerns;

class MyOtherPolicy implements MyOtherPolicyContract
{
public function two(): bool
{
return true;
}
}
10 changes: 10 additions & 0 deletions tests/Feature/Testing/Providers/Concerns/MyOtherPolicyContract.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Tests\LaraStrict\Feature\Testing\Providers\Concerns;

interface MyOtherPolicyContract
{
public function two(): bool;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Tests\LaraStrict\Feature\Testing\Providers\Concerns;

use LaraStrict\Contracts\HasPolicies;
use LaraStrict\Providers\AbstractServiceProvider;

class ProviderPolicyServiceProvider extends AbstractServiceProvider implements HasPolicies
{
public array $bindings = [
MyOtherPolicyContract::class => MyOtherPolicy::class,
];

public function policies(): array
{
return [
TestPolicy::class => TestPolicy::class,
MyOtherPolicyContract::class => MyOtherPolicy::class,
];
}
}
13 changes: 13 additions & 0 deletions tests/Feature/Testing/Providers/Concerns/TestPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Tests\LaraStrict\Feature\Testing\Providers\Concerns;

class TestPolicy extends MyOtherPolicy
{
public function one(): bool
{
return true;
}
}
4 changes: 2 additions & 2 deletions tests/Feature/Testing/TestServiceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ public function makeExpectationCommandData(): array
*/
public function testMakeExpectationCommand(string|EnvironmentType $environment, bool $has): void
{
/** @var Repository $config */
$config = $this->app()
->get(Repository::class);
assert($config instanceof Repository);
$config->set('app.env', $environment);

$this->app()
->register(LaraStrictServiceProvider::class);

/** @var Kernel $kernel */
$kernel = $this->app()
->make(Kernel::class);
assert($kernel instanceof Kernel);

$this->assertEquals($has, array_key_exists('make:expectation', $kernel->all()));
}
Expand Down

0 comments on commit 1d55e84

Please sign in to comment.