Skip to content

Commit

Permalink
feat(Testing): Add concern for testing Assert classes
Browse files Browse the repository at this point in the history
  • Loading branch information
pionl committed Nov 22, 2022
1 parent 309230d commit ff0ea2c
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 90 deletions.
74 changes: 74 additions & 0 deletions src/Testing/Concerns/AssertExpectations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace LaraStrict\Testing\Concerns;

use LaraStrict\Testing\AbstractExpectationCallsMap;
use LaraStrict\Testing\Entities\AssertExpectationEntity;
use LogicException;

trait AssertExpectations
{
abstract public function expectException(string $exception): void;

abstract public function expectExceptionMessage(string $message): void;

/**
* @dataProvider data
*/
public function testEmpty(AssertExpectationEntity $expectation): void
{
$this->assertBadCall($expectation->methodName);
$assert = $this->createEmptyAssert();

$this->callExpectation($expectation, $assert);
}

/**
* @dataProvider data
*/
public function testCallsWithSecondFails(AssertExpectationEntity $expectation): void
{
/** @var AbstractExpectationCallsMap $assert */
$assert = call_user_func($expectation->createAssert, $expectation->createAssert);

$result = $this->callExpectation($expectation, $assert);

if ($expectation->checkResult) {
$expectedResult = $expectation->checkResultIsSelf ? $assert : $expectation->expectedResult;
$this->assertSame($expectedResult, $result);
}

$this->assertBadCall(method: $expectation->methodName, callNumber: 2);
$this->callExpectation($expectation, $assert);
}

public function data(): array
{
$data = [];
foreach ($this->generateData() as $index => $test) {
$data[$test->methodName . ' #' . $index] = [$test];
}

return $data;
}

/**
* @return array<AssertExpectationEntity>
*/
abstract protected function generateData(): array;

abstract protected function createEmptyAssert(): AbstractExpectationCallsMap;

protected function assertBadCall(string $method, int $callNumber = 1): void
{
$this->expectException(LogicException::class);
$this->expectExceptionMessage($method . '] not set for a n (' . $callNumber . ') call');
}

protected function callExpectation(AssertExpectationEntity $expectation, AbstractExpectationCallsMap $assert): mixed
{
return call_user_func($expectation->call, $assert);
}
}
27 changes: 27 additions & 0 deletions src/Testing/Entities/AssertExpectationEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace LaraStrict\Testing\Entities;

use Closure;

class AssertExpectationEntity
{
/**
* @template TAssert
* @template TResult
* @param Closure():TAssert $createAssert
* @param Closure(TAssert):(TResult|void) $call
* @param TResult|null $expectedResult If null is passed then created assert will be used.
*/
public function __construct(
public readonly string $methodName,
public readonly Closure $createAssert,
public readonly Closure $call,
public readonly bool $checkResult = false,
public readonly bool $checkResultIsSelf = false,
public readonly mixed $expectedResult = null,
) {
}
}

This file was deleted.

110 changes: 46 additions & 64 deletions tests/Unit/Testing/Contracts/Auth/Access/GateAssertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Illuminate\Auth\Access\Response;
use Illuminate\Foundation\Auth\User;
use LaraStrict\Testing\AbstractExpectationCallsMap;
use LaraStrict\Testing\Concerns\AssertExpectations;
use LaraStrict\Testing\Entities\AssertExpectationEntity;
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GateAbilitiesExpectation;
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GateAfterExpectation;
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GateAllowsExpectation;
Expand All @@ -23,211 +26,190 @@
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GatePolicyExpectation;
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GateRawExpectation;
use LaraStrict\Testing\Laravel\Contracts\Auth\Access\GateResourceExpectation;
use LogicException;
use PHPUnit\Framework\TestCase;
use Tests\LaraStrict\Feature\Providers\Pipes\RegisterProviderPoliciesPipe\TestPolicy;
use Tests\LaraStrict\Feature\Testing\Commands\MakeExpectationCommand\TestAction;

class GateAssertTest extends TestCase
{
/**
* @dataProvider data
*/
public function testEmpty(GateAssertExpectationEntity $expectation): void
{
$this->assertBadCall($expectation->methodName);
$assert = new GateAssert();

$this->callExpectation($expectation, $assert);
}
use AssertExpectations;

/**
* @dataProvider data
*/
public function testCallsWithSecondFails(GateAssertExpectationEntity $expectation): void
{
/** @var GateAssert $assert */
$assert = call_user_func($expectation->createAssert, $expectation->createAssert);

$this->assertSame($expectation->expectedResult ?? $assert, $this->callExpectation($expectation, $assert));

$this->assertBadCall(method: $expectation->methodName, callNumber: 2);
$this->callExpectation($expectation, $assert);
}

public function data(): array
public function generateData(): array
{
$authorizeResponse = new Response(true);

$callback = static function () {
};
$testPolicy = new TestPolicy();
$user = new User();
$tests = [
new GateAssertExpectationEntity(
return [
new AssertExpectationEntity(
methodName: 'has',
createAssert: static fn () => new GateAssert(has: [new GateHasExpectation(
return: false,
ability: 's',
)]),
call: static fn (GateAssert $assert) => $assert->has('s'),
checkResult: true,
expectedResult: false,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'define',
createAssert: static fn () => new GateAssert(define: [new GateDefineExpectation(
ability: 's',
callback: 'test',
)]),
call: static fn (GateAssert $assert) => $assert->define('s', 'test'),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'resource',
createAssert: static fn () => new GateAssert(resource: [new GateResourceExpectation(
name: 'test',
class: TestAction::class,
abilities: ['asd'],
)]),
call: static fn (GateAssert $assert) => $assert->resource('test', TestAction::class, ['asd']),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'policy',
createAssert: static fn () => new GateAssert(policy: [new GatePolicyExpectation(
class: TestPolicy::class,
policy: 'testPolicy',
)]),
call: static fn (GateAssert $assert) => $assert->policy(TestPolicy::class, 'testPolicy'),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'before',
createAssert: static fn () => new GateAssert(before: [new GateBeforeExpectation(
callback: $callback
)]),
call: static fn (GateAssert $assert) => $assert->before($callback),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'after',
createAssert: static fn () => new GateAssert(after: [new GateAfterExpectation(
callback: $callback
)]),
call: static fn (GateAssert $assert) => $assert->after($callback),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'allows',
createAssert: static fn () => new GateAssert(allows: [new GateAllowsExpectation(
return: true,
ability: 'test',
arguments: ['test']
)]),
call: static fn (GateAssert $assert) => $assert->allows('test', ['test']),
checkResult: true,
expectedResult: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'denies',
createAssert: static fn () => new GateAssert(denies: [new GateDeniesExpectation(
return: false,
ability: 'test',
arguments: ['test']
)]),
call: static fn (GateAssert $assert) => $assert->denies('test', ['test']),
checkResult: true,
expectedResult: false,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'check',
createAssert: static fn () => new GateAssert(check: [new GateCheckExpectation(
return: true,
abilities: ['ability'],
arguments: ['test'],
)]),
call: static fn (GateAssert $assert) => $assert->check(['ability'], ['test']),
checkResult: true,
expectedResult: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'any',
createAssert: static fn () => new GateAssert(any: [new GateAnyExpectation(
return: true,
abilities: ['ability'],
arguments: ['test'],
)]),
call: static fn (GateAssert $assert) => $assert->any(['ability'], ['test']),
checkResult: true,
expectedResult: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'authorize',
createAssert: static fn () => new GateAssert(authorize: [new GateAuthorizeExpectation(
return: $authorizeResponse,
ability: 's',
arguments: ['test']
)]),
call: static fn (GateAssert $assert) => $assert->authorize('s', ['test']),
checkResult: true,
expectedResult: $authorizeResponse,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'inspect',
createAssert: static fn () => new GateAssert(inspect: [new GateInspectExpectation(
return: $authorizeResponse,
ability: 'ability',
arguments: ['test'],
)]),
call: static fn (GateAssert $assert) => $assert->inspect('ability', ['test']),
checkResult: true,
expectedResult: $authorizeResponse,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'raw',
createAssert: static fn () => new GateAssert(raw: [new GateRawExpectation(
return: $authorizeResponse,
ability: 'ability',
arguments: ['test'],
)]),
call: static fn (GateAssert $assert) => $assert->raw('ability', ['test']),
checkResult: true,
expectedResult: $authorizeResponse,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'getPolicyFor',
createAssert: static fn () => new GateAssert(getPolicyFor: [new GateGetPolicyForExpectation(
return: $testPolicy,
class: TestPolicy::class,
)]),
call: static fn (GateAssert $assert) => $assert->getPolicyFor(TestPolicy::class),
checkResult: true,
expectedResult: $testPolicy,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'forUser',
createAssert: static fn () => new GateAssert(forUser: [new GateForUserExpectation(user: $user,)]),
call: static fn (GateAssert $assert) => $assert->forUser($user),
expectedResult: null,
checkResult: true,
checkResultIsSelf: true,
),
new GateAssertExpectationEntity(
new AssertExpectationEntity(
methodName: 'abilities',
createAssert: static fn () => new GateAssert(abilities: [new GateAbilitiesExpectation(
return: ['test'],
)]),
call: static fn (GateAssert $assert) => $assert->abilities(),
checkResult: true,
expectedResult: ['test'],
),
];

$data = [];
foreach ($tests as $test) {
$data[$test->methodName] = [$test];
}

return $data;
}

protected function assertBadCall(string $method, int $callNumber = 1): void
{
$this->expectException(LogicException::class);
$this->expectExceptionMessage($method . '] not set for a n (' . $callNumber . ') call');
}

protected function callExpectation(GateAssertExpectationEntity $expectation, GateAssert $assert): mixed
protected function createEmptyAssert(): AbstractExpectationCallsMap
{
return call_user_func($expectation->call, $assert);
return new GateAssert();
}
}

0 comments on commit ff0ea2c

Please sign in to comment.