diff --git a/src/Traits/TestTraits/PhpUnit/TestAssertionHelperTrait.php b/src/Traits/TestTraits/PhpUnit/TestAssertionHelperTrait.php index dd7e34e7..8530cd62 100644 --- a/src/Traits/TestTraits/PhpUnit/TestAssertionHelperTrait.php +++ b/src/Traits/TestTraits/PhpUnit/TestAssertionHelperTrait.php @@ -7,6 +7,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Schema; use JetBrains\PhpStorm\Deprecated; +use Mockery\MockInterface; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; @@ -94,4 +95,76 @@ protected function getInaccessiblePropertyValue(object $object, string $property return $property->getValue($object); } + + /** + * Create a spy for an Action, SubAction or a Task that uses a repository. + * + * @param string $className the Action, SubAction or a Task class name + * @param string $repositoryClassName the repository class name + */ + protected function createSpyWithRepository(string $className, string $repositoryClassName, bool $allowRun = true): MockInterface + { + /** @var MockInterface $taskSpy */ + $taskSpy = \Mockery::mock($className, [app($repositoryClassName)]) + ->shouldIgnoreMissing(null, true) + ->makePartial(); + + if ($allowRun) { + $taskSpy->allows('run')->andReturn(); + } + + $this->swap($className, $taskSpy); + + return $taskSpy; + } + + /** + * Mock a repository and assert that the given criteria is pushed to it. + * + * @param string $repositoryClassName the repository class name + * @param string $criteriaClassName the criteria class name + * @param array|null $criteriaArgs the criteria constructor arguments + * + * @return MockInterface repository mock + * + * @example $this-> + * assertCriteriaPushedToRepository(UserRepository::class, SearchUsersCriteria::class, ['parameterName' => 'value']); + */ + protected function assertCriteriaPushedToRepository(string $repositoryClassName, string $criteriaClassName, array|null $criteriaArgs = null): MockInterface + { + $repositoryMock = $this->mock($repositoryClassName); + + if (is_null($criteriaArgs)) { + $repositoryMock->expects('pushCriteria')->once(); + } else { + $repositoryMock->expects('pushCriteriaWith')->once()->with($criteriaClassName, $criteriaArgs); + } + + return $repositoryMock; + } + + /** + * Assert that no criteria are pushed to the repository. + * + * @param string $repositoryClassName the repository class name + * + * @return MockInterface repository mock + */ + protected function assertNoCriteriaPushedToRepository(string $repositoryClassName): MockInterface + { + $repositoryMock = $this->mock($repositoryClassName); + $repositoryMock->expects('pushCriteria')->never(); + + return $repositoryMock; + } + + /** + * Allow "addRequestCriteria" method invocation on the repository mock. + * This is particularly useful when you want to test a repository that uses the RequestCriteria + * (e.g., for search and filtering). + */ + protected function allowAddRequestCriteriaInvocation(MockInterface $repositoryMock): void + { + $repositoryMock->allows('addRequestCriteria')->andReturnSelf(); + } }