This commit is contained in:
2022-07-18 08:00:16 +03:00
parent 42dd4c60f2
commit 42a8133706
2387 changed files with 210708 additions and 29 deletions

View File

@@ -0,0 +1,142 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Carbon\CarbonImmutable;
use Closure;
use Illuminate\Bus\Batch;
use Illuminate\Bus\BatchRepository;
use Illuminate\Bus\PendingBatch;
use Illuminate\Bus\UpdatedBatchJobCounts;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
class BatchRepositoryFake implements BatchRepository
{
/**
* Retrieve a list of batches.
*
* @param int $limit
* @param mixed $before
* @return \Illuminate\Bus\Batch[]
*/
public function get($limit, $before)
{
return [];
}
/**
* Retrieve information about an existing batch.
*
* @param string $batchId
* @return \Illuminate\Bus\Batch|null
*/
public function find(string $batchId)
{
//
}
/**
* Store a new pending batch.
*
* @param \Illuminate\Bus\PendingBatch $batch
* @return \Illuminate\Bus\Batch
*/
public function store(PendingBatch $batch)
{
return new Batch(
new QueueFake(Facade::getFacadeApplication()),
$this,
(string) Str::orderedUuid(),
$batch->name,
count($batch->jobs),
count($batch->jobs),
0,
[],
$batch->options,
CarbonImmutable::now(),
null,
null
);
}
/**
* Increment the total number of jobs within the batch.
*
* @param string $batchId
* @param int $amount
* @return void
*/
public function incrementTotalJobs(string $batchId, int $amount)
{
//
}
/**
* Decrement the total number of pending jobs for the batch.
*
* @param string $batchId
* @param string $jobId
* @return \Illuminate\Bus\UpdatedBatchJobCounts
*/
public function decrementPendingJobs(string $batchId, string $jobId)
{
return new UpdatedBatchJobCounts;
}
/**
* Increment the total number of failed jobs for the batch.
*
* @param string $batchId
* @param string $jobId
* @return \Illuminate\Bus\UpdatedBatchJobCounts
*/
public function incrementFailedJobs(string $batchId, string $jobId)
{
return new UpdatedBatchJobCounts;
}
/**
* Mark the batch that has the given ID as finished.
*
* @param string $batchId
* @return void
*/
public function markAsFinished(string $batchId)
{
//
}
/**
* Cancel the batch that has the given ID.
*
* @param string $batchId
* @return void
*/
public function cancel(string $batchId)
{
//
}
/**
* Delete the batch that has the given ID.
*
* @param string $batchId
* @return void
*/
public function delete(string $batchId)
{
//
}
/**
* Execute the given Closure within a storage specific transaction.
*
* @param \Closure $callback
* @return mixed
*/
public function transaction(Closure $callback)
{
return $callback();
}
}

View File

@@ -0,0 +1,721 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Illuminate\Bus\PendingBatch;
use Illuminate\Contracts\Bus\QueueingDispatcher;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
class BusFake implements QueueingDispatcher
{
use ReflectsClosures;
/**
* The original Bus dispatcher implementation.
*
* @var \Illuminate\Contracts\Bus\QueueingDispatcher
*/
protected $dispatcher;
/**
* The job types that should be intercepted instead of dispatched.
*
* @var array
*/
protected $jobsToFake;
/**
* The commands that have been dispatched.
*
* @var array
*/
protected $commands = [];
/**
* The commands that have been dispatched synchronously.
*
* @var array
*/
protected $commandsSync = [];
/**
* The commands that have been dispatched after the response has been sent.
*
* @var array
*/
protected $commandsAfterResponse = [];
/**
* The batches that have been dispatched.
*
* @var array
*/
protected $batches = [];
/**
* Create a new bus fake instance.
*
* @param \Illuminate\Contracts\Bus\QueueingDispatcher $dispatcher
* @param array|string $jobsToFake
* @return void
*/
public function __construct(QueueingDispatcher $dispatcher, $jobsToFake = [])
{
$this->dispatcher = $dispatcher;
$this->jobsToFake = Arr::wrap($jobsToFake);
}
/**
* Assert if a job was dispatched based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|int|null $callback
* @return void
*/
public function assertDispatched($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
if (is_numeric($callback)) {
return $this->assertDispatchedTimes($command, $callback);
}
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->count() > 0 ||
$this->dispatchedAfterResponse($command, $callback)->count() > 0 ||
$this->dispatchedSync($command, $callback)->count() > 0,
"The expected [{$command}] job was not dispatched."
);
}
/**
* Assert if a job was pushed a number of times.
*
* @param string $command
* @param int $times
* @return void
*/
public function assertDispatchedTimes($command, $times = 1)
{
$count = $this->dispatched($command)->count() +
$this->dispatchedAfterResponse($command)->count() +
$this->dispatchedSync($command)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$command}] job was pushed {$count} times instead of {$times} times."
);
}
/**
* Determine if a job was dispatched based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|null $callback
* @return void
*/
public function assertNotDispatched($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->count() === 0 &&
$this->dispatchedAfterResponse($command, $callback)->count() === 0 &&
$this->dispatchedSync($command, $callback)->count() === 0,
"The unexpected [{$command}] job was dispatched."
);
}
/**
* Assert that no jobs were dispatched.
*
* @return void
*/
public function assertNothingDispatched()
{
PHPUnit::assertEmpty($this->commands, 'Jobs were dispatched unexpectedly.');
}
/**
* Assert if a job was explicitly dispatched synchronously based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|int|null $callback
* @return void
*/
public function assertDispatchedSync($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
if (is_numeric($callback)) {
return $this->assertDispatchedSyncTimes($command, $callback);
}
PHPUnit::assertTrue(
$this->dispatchedSync($command, $callback)->count() > 0,
"The expected [{$command}] job was not dispatched synchronously."
);
}
/**
* Assert if a job was pushed synchronously a number of times.
*
* @param string $command
* @param int $times
* @return void
*/
public function assertDispatchedSyncTimes($command, $times = 1)
{
$count = $this->dispatchedSync($command)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$command}] job was synchronously pushed {$count} times instead of {$times} times."
);
}
/**
* Determine if a job was dispatched based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|null $callback
* @return void
*/
public function assertNotDispatchedSync($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
PHPUnit::assertCount(
0, $this->dispatchedSync($command, $callback),
"The unexpected [{$command}] job was dispatched synchronously."
);
}
/**
* Assert if a job was dispatched after the response was sent based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|int|null $callback
* @return void
*/
public function assertDispatchedAfterResponse($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
if (is_numeric($callback)) {
return $this->assertDispatchedAfterResponseTimes($command, $callback);
}
PHPUnit::assertTrue(
$this->dispatchedAfterResponse($command, $callback)->count() > 0,
"The expected [{$command}] job was not dispatched after sending the response."
);
}
/**
* Assert if a job was pushed after the response was sent a number of times.
*
* @param string $command
* @param int $times
* @return void
*/
public function assertDispatchedAfterResponseTimes($command, $times = 1)
{
$count = $this->dispatchedAfterResponse($command)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$command}] job was pushed {$count} times instead of {$times} times."
);
}
/**
* Determine if a job was dispatched based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|null $callback
* @return void
*/
public function assertNotDispatchedAfterResponse($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
PHPUnit::assertCount(
0, $this->dispatchedAfterResponse($command, $callback),
"The unexpected [{$command}] job was dispatched after sending the response."
);
}
/**
* Assert if a chain of jobs was dispatched.
*
* @param array $expectedChain
* @return void
*/
public function assertChained(array $expectedChain)
{
$command = $expectedChain[0];
$expectedChain = array_slice($expectedChain, 1);
$callback = null;
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
} elseif (! is_string($command)) {
$instance = $command;
$command = get_class($instance);
$callback = function ($job) use ($instance) {
return serialize($this->resetChainPropertiesToDefaults($job)) === serialize($instance);
};
}
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->isNotEmpty(),
"The expected [{$command}] job was not dispatched."
);
PHPUnit::assertTrue(
collect($expectedChain)->isNotEmpty(),
'The expected chain can not be empty.'
);
$this->isChainOfObjects($expectedChain)
? $this->assertDispatchedWithChainOfObjects($command, $expectedChain, $callback)
: $this->assertDispatchedWithChainOfClasses($command, $expectedChain, $callback);
}
/**
* Reset the chain properties to their default values on the job.
*
* @param mixed $job
* @return mixed
*/
protected function resetChainPropertiesToDefaults($job)
{
return tap(clone $job, function ($job) {
$job->chainConnection = null;
$job->chainQueue = null;
$job->chainCatchCallbacks = null;
$job->chained = [];
});
}
/**
* Assert if a job was dispatched with an empty chain based on a truth-test callback.
*
* @param string|\Closure $command
* @param callable|null $callback
* @return void
*/
public function assertDispatchedWithoutChain($command, $callback = null)
{
if ($command instanceof Closure) {
[$command, $callback] = [$this->firstClosureParameterType($command), $command];
}
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->isNotEmpty(),
"The expected [{$command}] job was not dispatched."
);
$this->assertDispatchedWithChainOfClasses($command, [], $callback);
}
/**
* Assert if a job was dispatched with chained jobs based on a truth-test callback.
*
* @param string $command
* @param array $expectedChain
* @param callable|null $callback
* @return void
*/
protected function assertDispatchedWithChainOfObjects($command, $expectedChain, $callback)
{
$chain = collect($expectedChain)->map(fn ($job) => serialize($job))->all();
PHPUnit::assertTrue(
$this->dispatched($command, $callback)->filter(
fn ($job) => $job->chained == $chain
)->isNotEmpty(),
'The expected chain was not dispatched.'
);
}
/**
* Assert if a job was dispatched with chained jobs based on a truth-test callback.
*
* @param string $command
* @param array $expectedChain
* @param callable|null $callback
* @return void
*/
protected function assertDispatchedWithChainOfClasses($command, $expectedChain, $callback)
{
$matching = $this->dispatched($command, $callback)->map->chained->map(function ($chain) {
return collect($chain)->map(
fn ($job) => get_class(unserialize($job))
);
})->filter(
fn ($chain) => $chain->all() === $expectedChain
);
PHPUnit::assertTrue(
$matching->isNotEmpty(), 'The expected chain was not dispatched.'
);
}
/**
* Determine if the given chain is entirely composed of objects.
*
* @param array $chain
* @return bool
*/
protected function isChainOfObjects($chain)
{
return ! collect($chain)->contains(fn ($job) => ! is_object($job));
}
/**
* Assert if a batch was dispatched based on a truth-test callback.
*
* @param callable $callback
* @return void
*/
public function assertBatched(callable $callback)
{
PHPUnit::assertTrue(
$this->batched($callback)->count() > 0,
'The expected batch was not dispatched.'
);
}
/**
* Assert the number of batches that have been dispatched.
*
* @param int $count
* @return void
*/
public function assertBatchCount($count)
{
PHPUnit::assertCount(
$count, $this->batches,
);
}
/**
* Get all of the jobs matching a truth-test callback.
*
* @param string $command
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function dispatched($command, $callback = null)
{
if (! $this->hasDispatched($command)) {
return collect();
}
$callback = $callback ?: fn () => true;
return collect($this->commands[$command])->filter(fn ($command) => $callback($command));
}
/**
* Get all of the jobs dispatched synchronously matching a truth-test callback.
*
* @param string $command
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function dispatchedSync(string $command, $callback = null)
{
if (! $this->hasDispatchedSync($command)) {
return collect();
}
$callback = $callback ?: fn () => true;
return collect($this->commandsSync[$command])->filter(fn ($command) => $callback($command));
}
/**
* Get all of the jobs dispatched after the response was sent matching a truth-test callback.
*
* @param string $command
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function dispatchedAfterResponse(string $command, $callback = null)
{
if (! $this->hasDispatchedAfterResponse($command)) {
return collect();
}
$callback = $callback ?: fn () => true;
return collect($this->commandsAfterResponse[$command])->filter(fn ($command) => $callback($command));
}
/**
* Get all of the pending batches matching a truth-test callback.
*
* @param callable $callback
* @return \Illuminate\Support\Collection
*/
public function batched(callable $callback)
{
if (empty($this->batches)) {
return collect();
}
return collect($this->batches)->filter(fn ($batch) => $callback($batch));
}
/**
* Determine if there are any stored commands for a given class.
*
* @param string $command
* @return bool
*/
public function hasDispatched($command)
{
return isset($this->commands[$command]) && ! empty($this->commands[$command]);
}
/**
* Determine if there are any stored commands for a given class.
*
* @param string $command
* @return bool
*/
public function hasDispatchedSync($command)
{
return isset($this->commandsSync[$command]) && ! empty($this->commandsSync[$command]);
}
/**
* Determine if there are any stored commands for a given class.
*
* @param string $command
* @return bool
*/
public function hasDispatchedAfterResponse($command)
{
return isset($this->commandsAfterResponse[$command]) && ! empty($this->commandsAfterResponse[$command]);
}
/**
* Dispatch a command to its appropriate handler.
*
* @param mixed $command
* @return mixed
*/
public function dispatch($command)
{
if ($this->shouldFakeJob($command)) {
$this->commands[get_class($command)][] = $command;
} else {
return $this->dispatcher->dispatch($command);
}
}
/**
* Dispatch a command to its appropriate handler in the current process.
*
* Queueable jobs will be dispatched to the "sync" queue.
*
* @param mixed $command
* @param mixed $handler
* @return mixed
*/
public function dispatchSync($command, $handler = null)
{
if ($this->shouldFakeJob($command)) {
$this->commandsSync[get_class($command)][] = $command;
} else {
return $this->dispatcher->dispatchSync($command, $handler);
}
}
/**
* Dispatch a command to its appropriate handler in the current process.
*
* @param mixed $command
* @param mixed $handler
* @return mixed
*/
public function dispatchNow($command, $handler = null)
{
if ($this->shouldFakeJob($command)) {
$this->commands[get_class($command)][] = $command;
} else {
return $this->dispatcher->dispatchNow($command, $handler);
}
}
/**
* Dispatch a command to its appropriate handler behind a queue.
*
* @param mixed $command
* @return mixed
*/
public function dispatchToQueue($command)
{
if ($this->shouldFakeJob($command)) {
$this->commands[get_class($command)][] = $command;
} else {
return $this->dispatcher->dispatchToQueue($command);
}
}
/**
* Dispatch a command to its appropriate handler.
*
* @param mixed $command
* @return mixed
*/
public function dispatchAfterResponse($command)
{
if ($this->shouldFakeJob($command)) {
$this->commandsAfterResponse[get_class($command)][] = $command;
} else {
return $this->dispatcher->dispatch($command);
}
}
/**
* Create a new chain of queueable jobs.
*
* @param \Illuminate\Support\Collection|array $jobs
* @return \Illuminate\Foundation\Bus\PendingChain
*/
public function chain($jobs)
{
$jobs = Collection::wrap($jobs);
return new PendingChainFake($this, $jobs->shift(), $jobs->toArray());
}
/**
* Attempt to find the batch with the given ID.
*
* @param string $batchId
* @return \Illuminate\Bus\Batch|null
*/
public function findBatch(string $batchId)
{
//
}
/**
* Create a new batch of queueable jobs.
*
* @param \Illuminate\Support\Collection|array $jobs
* @return \Illuminate\Bus\PendingBatch
*/
public function batch($jobs)
{
return new PendingBatchFake($this, Collection::wrap($jobs));
}
/**
* Record the fake pending batch dispatch.
*
* @param \Illuminate\Bus\PendingBatch $pendingBatch
* @return \Illuminate\Bus\Batch
*/
public function recordPendingBatch(PendingBatch $pendingBatch)
{
$this->batches[] = $pendingBatch;
return (new BatchRepositoryFake)->store($pendingBatch);
}
/**
* Determine if a command should be faked or actually dispatched.
*
* @param mixed $command
* @return bool
*/
protected function shouldFakeJob($command)
{
if (empty($this->jobsToFake)) {
return true;
}
return collect($this->jobsToFake)
->filter(function ($job) use ($command) {
return $job instanceof Closure
? $job($command)
: $job === get_class($command);
})->isNotEmpty();
}
/**
* Set the pipes commands should be piped through before dispatching.
*
* @param array $pipes
* @return $this
*/
public function pipeThrough(array $pipes)
{
$this->dispatcher->pipeThrough($pipes);
return $this;
}
/**
* Determine if the given command has a handler.
*
* @param mixed $command
* @return bool
*/
public function hasCommandHandler($command)
{
return $this->dispatcher->hasCommandHandler($command);
}
/**
* Retrieve the handler for a command.
*
* @param mixed $command
* @return mixed
*/
public function getCommandHandler($command)
{
return $this->dispatcher->getCommandHandler($command);
}
/**
* Map a command to a handler.
*
* @param array $map
* @return $this
*/
public function map(array $map)
{
$this->dispatcher->map($map);
return $this;
}
}

View File

@@ -0,0 +1,331 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
use ReflectionFunction;
class EventFake implements Dispatcher
{
use ReflectsClosures;
/**
* The original event dispatcher.
*
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected $dispatcher;
/**
* The event types that should be intercepted instead of dispatched.
*
* @var array
*/
protected $eventsToFake;
/**
* All of the events that have been intercepted keyed by type.
*
* @var array
*/
protected $events = [];
/**
* Create a new event fake instance.
*
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
* @param array|string $eventsToFake
* @return void
*/
public function __construct(Dispatcher $dispatcher, $eventsToFake = [])
{
$this->dispatcher = $dispatcher;
$this->eventsToFake = Arr::wrap($eventsToFake);
}
/**
* Assert if an event has a listener attached to it.
*
* @param string $expectedEvent
* @param string|array $expectedListener
* @return void
*/
public function assertListening($expectedEvent, $expectedListener)
{
foreach ($this->dispatcher->getListeners($expectedEvent) as $listenerClosure) {
$actualListener = (new ReflectionFunction($listenerClosure))
->getStaticVariables()['listener'];
if (is_string($actualListener) && Str::contains($actualListener, '@')) {
$actualListener = Str::parseCallback($actualListener);
if (is_string($expectedListener)) {
if (Str::contains($expectedListener, '@')) {
$expectedListener = Str::parseCallback($expectedListener);
} else {
$expectedListener = [$expectedListener, 'handle'];
}
}
}
if ($actualListener === $expectedListener ||
($actualListener instanceof Closure &&
$expectedListener === Closure::class)) {
PHPUnit::assertTrue(true);
return;
}
}
PHPUnit::assertTrue(
false,
sprintf(
'Event [%s] does not have the [%s] listener attached to it',
$expectedEvent,
print_r($expectedListener, true)
)
);
}
/**
* Assert if an event was dispatched based on a truth-test callback.
*
* @param string|\Closure $event
* @param callable|int|null $callback
* @return void
*/
public function assertDispatched($event, $callback = null)
{
if ($event instanceof Closure) {
[$event, $callback] = [$this->firstClosureParameterType($event), $event];
}
if (is_int($callback)) {
return $this->assertDispatchedTimes($event, $callback);
}
PHPUnit::assertTrue(
$this->dispatched($event, $callback)->count() > 0,
"The expected [{$event}] event was not dispatched."
);
}
/**
* Assert if an event was dispatched a number of times.
*
* @param string $event
* @param int $times
* @return void
*/
public function assertDispatchedTimes($event, $times = 1)
{
$count = $this->dispatched($event)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$event}] event was dispatched {$count} times instead of {$times} times."
);
}
/**
* Determine if an event was dispatched based on a truth-test callback.
*
* @param string|\Closure $event
* @param callable|null $callback
* @return void
*/
public function assertNotDispatched($event, $callback = null)
{
if ($event instanceof Closure) {
[$event, $callback] = [$this->firstClosureParameterType($event), $event];
}
PHPUnit::assertCount(
0, $this->dispatched($event, $callback),
"The unexpected [{$event}] event was dispatched."
);
}
/**
* Assert that no events were dispatched.
*
* @return void
*/
public function assertNothingDispatched()
{
$count = count(Arr::flatten($this->events));
PHPUnit::assertSame(
0, $count,
"{$count} unexpected events were dispatched."
);
}
/**
* Get all of the events matching a truth-test callback.
*
* @param string $event
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function dispatched($event, $callback = null)
{
if (! $this->hasDispatched($event)) {
return collect();
}
$callback = $callback ?: fn () => true;
return collect($this->events[$event])->filter(
fn ($arguments) => $callback(...$arguments)
);
}
/**
* Determine if the given event has been dispatched.
*
* @param string $event
* @return bool
*/
public function hasDispatched($event)
{
return isset($this->events[$event]) && ! empty($this->events[$event]);
}
/**
* Register an event listener with the dispatcher.
*
* @param \Closure|string|array $events
* @param mixed $listener
* @return void
*/
public function listen($events, $listener = null)
{
$this->dispatcher->listen($events, $listener);
}
/**
* Determine if a given event has listeners.
*
* @param string $eventName
* @return bool
*/
public function hasListeners($eventName)
{
return $this->dispatcher->hasListeners($eventName);
}
/**
* Register an event and payload to be dispatched later.
*
* @param string $event
* @param array $payload
* @return void
*/
public function push($event, $payload = [])
{
//
}
/**
* Register an event subscriber with the dispatcher.
*
* @param object|string $subscriber
* @return void
*/
public function subscribe($subscriber)
{
$this->dispatcher->subscribe($subscriber);
}
/**
* Flush a set of pushed events.
*
* @param string $event
* @return void
*/
public function flush($event)
{
//
}
/**
* Fire an event and call the listeners.
*
* @param string|object $event
* @param mixed $payload
* @param bool $halt
* @return array|null
*/
public function dispatch($event, $payload = [], $halt = false)
{
$name = is_object($event) ? get_class($event) : (string) $event;
if ($this->shouldFakeEvent($name, $payload)) {
$this->events[$name][] = func_get_args();
} else {
return $this->dispatcher->dispatch($event, $payload, $halt);
}
}
/**
* Determine if an event should be faked or actually dispatched.
*
* @param string $eventName
* @param mixed $payload
* @return bool
*/
protected function shouldFakeEvent($eventName, $payload)
{
if (empty($this->eventsToFake)) {
return true;
}
return collect($this->eventsToFake)
->filter(function ($event) use ($eventName, $payload) {
return $event instanceof Closure
? $event($eventName, $payload)
: $event === $eventName;
})
->isNotEmpty();
}
/**
* Remove a set of listeners from the dispatcher.
*
* @param string $event
* @return void
*/
public function forget($event)
{
//
}
/**
* Forget all of the queued listeners.
*
* @return void
*/
public function forgetPushed()
{
//
}
/**
* Dispatch an event and call the listeners.
*
* @param string|object $event
* @param mixed $payload
* @return array|null
*/
public function until($event, $payload = [])
{
return $this->dispatch($event, $payload, true);
}
}

View File

@@ -0,0 +1,433 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Illuminate\Contracts\Mail\Factory;
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Mail\MailQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
class MailFake implements Factory, Mailer, MailQueue
{
use ReflectsClosures;
/**
* The mailer currently being used to send a message.
*
* @var string
*/
protected $currentMailer;
/**
* All of the mailables that have been sent.
*
* @var array
*/
protected $mailables = [];
/**
* All of the mailables that have been queued.
*
* @var array
*/
protected $queuedMailables = [];
/**
* Assert if a mailable was sent based on a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|int|null $callback
* @return void
*/
public function assertSent($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
if (is_numeric($callback)) {
return $this->assertSentTimes($mailable, $callback);
}
$message = "The expected [{$mailable}] mailable was not sent.";
if (count($this->queuedMailables) > 0) {
$message .= ' Did you mean to use assertQueued() instead?';
}
PHPUnit::assertTrue(
$this->sent($mailable, $callback)->count() > 0,
$message
);
}
/**
* Assert if a mailable was sent a number of times.
*
* @param string $mailable
* @param int $times
* @return void
*/
protected function assertSentTimes($mailable, $times = 1)
{
$count = $this->sent($mailable)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$mailable}] mailable was sent {$count} times instead of {$times} times."
);
}
/**
* Determine if a mailable was not sent or queued to be sent based on a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return void
*/
public function assertNotOutgoing($mailable, $callback = null)
{
$this->assertNotSent($mailable, $callback);
$this->assertNotQueued($mailable, $callback);
}
/**
* Determine if a mailable was not sent based on a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return void
*/
public function assertNotSent($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
PHPUnit::assertCount(
0, $this->sent($mailable, $callback),
"The unexpected [{$mailable}] mailable was sent."
);
}
/**
* Assert that no mailables were sent or queued to be sent.
*
* @return void
*/
public function assertNothingOutgoing()
{
$this->assertNothingSent();
$this->assertNothingQueued();
}
/**
* Assert that no mailables were sent.
*
* @return void
*/
public function assertNothingSent()
{
$mailableNames = collect($this->mailables)->map(
fn ($mailable) => get_class($mailable)
)->join(', ');
PHPUnit::assertEmpty($this->mailables, 'The following mailables were sent unexpectedly: '.$mailableNames);
}
/**
* Assert if a mailable was queued based on a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|int|null $callback
* @return void
*/
public function assertQueued($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
if (is_numeric($callback)) {
return $this->assertQueuedTimes($mailable, $callback);
}
PHPUnit::assertTrue(
$this->queued($mailable, $callback)->count() > 0,
"The expected [{$mailable}] mailable was not queued."
);
}
/**
* Assert if a mailable was queued a number of times.
*
* @param string $mailable
* @param int $times
* @return void
*/
protected function assertQueuedTimes($mailable, $times = 1)
{
$count = $this->queued($mailable)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$mailable}] mailable was queued {$count} times instead of {$times} times."
);
}
/**
* Determine if a mailable was not queued based on a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return void
*/
public function assertNotQueued($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
PHPUnit::assertCount(
0, $this->queued($mailable, $callback),
"The unexpected [{$mailable}] mailable was queued."
);
}
/**
* Assert that no mailables were queued.
*
* @return void
*/
public function assertNothingQueued()
{
$mailableNames = collect($this->queuedMailables)->map(
fn ($mailable) => get_class($mailable)
)->join(', ');
PHPUnit::assertEmpty($this->queuedMailables, 'The following mailables were queued unexpectedly: '.$mailableNames);
}
/**
* Get all of the mailables matching a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function sent($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
if (! $this->hasSent($mailable)) {
return collect();
}
$callback = $callback ?: fn () => true;
return $this->mailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable));
}
/**
* Determine if the given mailable has been sent.
*
* @param string $mailable
* @return bool
*/
public function hasSent($mailable)
{
return $this->mailablesOf($mailable)->count() > 0;
}
/**
* Get all of the queued mailables matching a truth-test callback.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function queued($mailable, $callback = null)
{
[$mailable, $callback] = $this->prepareMailableAndCallback($mailable, $callback);
if (! $this->hasQueued($mailable)) {
return collect();
}
$callback = $callback ?: fn () => true;
return $this->queuedMailablesOf($mailable)->filter(fn ($mailable) => $callback($mailable));
}
/**
* Determine if the given mailable has been queued.
*
* @param string $mailable
* @return bool
*/
public function hasQueued($mailable)
{
return $this->queuedMailablesOf($mailable)->count() > 0;
}
/**
* Get all of the mailed mailables for a given type.
*
* @param string $type
* @return \Illuminate\Support\Collection
*/
protected function mailablesOf($type)
{
return collect($this->mailables)->filter(fn ($mailable) => $mailable instanceof $type);
}
/**
* Get all of the mailed mailables for a given type.
*
* @param string $type
* @return \Illuminate\Support\Collection
*/
protected function queuedMailablesOf($type)
{
return collect($this->queuedMailables)->filter(fn ($mailable) => $mailable instanceof $type);
}
/**
* Get a mailer instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Mail\Mailer
*/
public function mailer($name = null)
{
$this->currentMailer = $name;
return $this;
}
/**
* Begin the process of mailing a mailable class instance.
*
* @param mixed $users
* @return \Illuminate\Mail\PendingMail
*/
public function to($users)
{
return (new PendingMailFake($this))->to($users);
}
/**
* Begin the process of mailing a mailable class instance.
*
* @param mixed $users
* @return \Illuminate\Mail\PendingMail
*/
public function bcc($users)
{
return (new PendingMailFake($this))->bcc($users);
}
/**
* Send a new message with only a raw text part.
*
* @param string $text
* @param \Closure|string $callback
* @return void
*/
public function raw($text, $callback)
{
//
}
/**
* Send a new message using a view.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return void
*/
public function send($view, array $data = [], $callback = null)
{
if (! $view instanceof Mailable) {
return;
}
$view->mailer($this->currentMailer);
if ($view instanceof ShouldQueue) {
return $this->queue($view, $data);
}
$this->currentMailer = null;
$this->mailables[] = $view;
}
/**
* Queue a new e-mail message for sending.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param string|null $queue
* @return mixed
*/
public function queue($view, $queue = null)
{
if (! $view instanceof Mailable) {
return;
}
$view->mailer($this->currentMailer);
$this->currentMailer = null;
$this->queuedMailables[] = $view;
}
/**
* Queue a new e-mail message for sending after (n) seconds.
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param string|null $queue
* @return mixed
*/
public function later($delay, $view, $queue = null)
{
$this->queue($view, $queue);
}
/**
* Get the array of failed recipients.
*
* @return array
*/
public function failures()
{
return [];
}
/**
* Infer mailable class using reflection if a typehinted closure is passed to assertion.
*
* @param string|\Closure $mailable
* @param callable|null $callback
* @return array
*/
protected function prepareMailableAndCallback($mailable, $callback)
{
if ($mailable instanceof Closure) {
return [$this->firstClosureParameterType($mailable), $mailable];
}
return [$mailable, $callback];
}
/**
* Forget all of the resolved mailer instances.
*
* @return $this
*/
public function forgetMailers()
{
$this->currentMailer = null;
return $this;
}
}

View File

@@ -0,0 +1,365 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Exception;
use Illuminate\Contracts\Notifications\Dispatcher as NotificationDispatcher;
use Illuminate\Contracts\Notifications\Factory as NotificationFactory;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
class NotificationFake implements NotificationDispatcher, NotificationFactory
{
use Macroable, ReflectsClosures;
/**
* All of the notifications that have been sent.
*
* @var array
*/
protected $notifications = [];
/**
* Locale used when sending notifications.
*
* @var string|null
*/
public $locale;
/**
* Assert if a notification was sent on-demand based on a truth-test callback.
*
* @param string|\Closure $notification
* @param callable|null $callback
* @return void
*
* @throws \Exception
*/
public function assertSentOnDemand($notification, $callback = null)
{
$this->assertSentTo(new AnonymousNotifiable, $notification, $callback);
}
/**
* Assert if a notification was sent based on a truth-test callback.
*
* @param mixed $notifiable
* @param string|\Closure $notification
* @param callable|null $callback
* @return void
*
* @throws \Exception
*/
public function assertSentTo($notifiable, $notification, $callback = null)
{
if (is_array($notifiable) || $notifiable instanceof Collection) {
if (count($notifiable) === 0) {
throw new Exception('No notifiable given.');
}
foreach ($notifiable as $singleNotifiable) {
$this->assertSentTo($singleNotifiable, $notification, $callback);
}
return;
}
if ($notification instanceof Closure) {
[$notification, $callback] = [$this->firstClosureParameterType($notification), $notification];
}
if (is_numeric($callback)) {
return $this->assertSentToTimes($notifiable, $notification, $callback);
}
PHPUnit::assertTrue(
$this->sent($notifiable, $notification, $callback)->count() > 0,
"The expected [{$notification}] notification was not sent."
);
}
/**
* Assert if a notification was sent on-demand a number of times.
*
* @param string $notification
* @param int $times
* @return void
*/
public function assertSentOnDemandTimes($notification, $times = 1)
{
return $this->assertSentToTimes(new AnonymousNotifiable, $notification, $times);
}
/**
* Assert if a notification was sent a number of times.
*
* @param mixed $notifiable
* @param string $notification
* @param int $times
* @return void
*/
public function assertSentToTimes($notifiable, $notification, $times = 1)
{
$count = $this->sent($notifiable, $notification)->count();
PHPUnit::assertSame(
$times, $count,
"Expected [{$notification}] to be sent {$times} times, but was sent {$count} times."
);
}
/**
* Determine if a notification was sent based on a truth-test callback.
*
* @param mixed $notifiable
* @param string|\Closure $notification
* @param callable|null $callback
* @return void
*
* @throws \Exception
*/
public function assertNotSentTo($notifiable, $notification, $callback = null)
{
if (is_array($notifiable) || $notifiable instanceof Collection) {
if (count($notifiable) === 0) {
throw new Exception('No notifiable given.');
}
foreach ($notifiable as $singleNotifiable) {
$this->assertNotSentTo($singleNotifiable, $notification, $callback);
}
return;
}
if ($notification instanceof Closure) {
[$notification, $callback] = [$this->firstClosureParameterType($notification), $notification];
}
PHPUnit::assertCount(
0, $this->sent($notifiable, $notification, $callback),
"The unexpected [{$notification}] notification was sent."
);
}
/**
* Assert that no notifications were sent.
*
* @return void
*/
public function assertNothingSent()
{
PHPUnit::assertEmpty($this->notifications, 'Notifications were sent unexpectedly.');
}
/**
* Assert that no notifications were sent to the given notifiable.
*
* @param mixed $notifiable
* @return void
*
* @throws \Exception
*/
public function assertNothingSentTo($notifiable)
{
if (is_array($notifiable) || $notifiable instanceof Collection) {
if (count($notifiable) === 0) {
throw new Exception('No notifiable given.');
}
foreach ($notifiable as $singleNotifiable) {
$this->assertNothingSentTo($singleNotifiable);
}
return;
}
PHPUnit::assertEmpty(
$this->notifications[get_class($notifiable)][$notifiable->getKey()] ?? [],
'Notifications were sent unexpectedly.',
);
}
/**
* Assert the total amount of times a notification was sent.
*
* @param string $notification
* @param int $expectedCount
* @return void
*/
public function assertSentTimes($notification, $expectedCount)
{
$actualCount = collect($this->notifications)
->flatten(1)
->reduce(fn ($count, $sent) => $count + count($sent[$notification] ?? []), 0);
PHPUnit::assertSame(
$expectedCount, $actualCount,
"Expected [{$notification}] to be sent {$expectedCount} times, but was sent {$actualCount} times."
);
}
/**
* Assert the total count of notification that were sent.
*
* @param int $expectedCount
* @return void
*/
public function assertCount($expectedCount)
{
$actualCount = collect($this->notifications)->flatten(3)->count();
PHPUnit::assertSame(
$expectedCount, $actualCount,
"Expected {$expectedCount} notifications to be sent, but {$actualCount} were sent."
);
}
/**
* Assert the total amount of times a notification was sent.
*
* @param int $expectedCount
* @param string $notification
* @return void
*
* @deprecated Use the assertSentTimes method instead
*/
public function assertTimesSent($expectedCount, $notification)
{
$this->assertSentTimes($notification, $expectedCount);
}
/**
* Get all of the notifications matching a truth-test callback.
*
* @param mixed $notifiable
* @param string $notification
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function sent($notifiable, $notification, $callback = null)
{
if (! $this->hasSent($notifiable, $notification)) {
return collect();
}
$callback = $callback ?: fn () => true;
$notifications = collect($this->notificationsFor($notifiable, $notification));
return $notifications->filter(
fn ($arguments) => $callback(...array_values($arguments))
)->pluck('notification');
}
/**
* Determine if there are more notifications left to inspect.
*
* @param mixed $notifiable
* @param string $notification
* @return bool
*/
public function hasSent($notifiable, $notification)
{
return ! empty($this->notificationsFor($notifiable, $notification));
}
/**
* Get all of the notifications for a notifiable entity by type.
*
* @param mixed $notifiable
* @param string $notification
* @return array
*/
protected function notificationsFor($notifiable, $notification)
{
return $this->notifications[get_class($notifiable)][$notifiable->getKey()][$notification] ?? [];
}
/**
* Send the given notification to the given notifiable entities.
*
* @param \Illuminate\Support\Collection|array|mixed $notifiables
* @param mixed $notification
* @return void
*/
public function send($notifiables, $notification)
{
$this->sendNow($notifiables, $notification);
}
/**
* Send the given notification immediately.
*
* @param \Illuminate\Support\Collection|array|mixed $notifiables
* @param mixed $notification
* @param array|null $channels
* @return void
*/
public function sendNow($notifiables, $notification, array $channels = null)
{
if (! $notifiables instanceof Collection && ! is_array($notifiables)) {
$notifiables = [$notifiables];
}
foreach ($notifiables as $notifiable) {
if (! $notification->id) {
$notification->id = Str::uuid()->toString();
}
$notifiableChannels = $channels ?: $notification->via($notifiable);
if (method_exists($notification, 'shouldSend')) {
$notifiableChannels = array_filter(
$notifiableChannels,
fn ($channel) => $notification->shouldSend($notifiable, $channel) !== false
);
if (empty($notifiableChannels)) {
continue;
}
}
$this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
'notification' => $notification,
'channels' => $notifiableChannels,
'notifiable' => $notifiable,
'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
if ($notifiable instanceof HasLocalePreference) {
return $notifiable->preferredLocale();
}
}),
];
}
}
/**
* Get a channel instance by name.
*
* @param string|null $name
* @return mixed
*/
public function channel($name = null)
{
//
}
/**
* Set the locale of notifications.
*
* @param string $locale
* @return $this
*/
public function locale($locale)
{
$this->locale = $locale;
return $this;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Collection;
class PendingBatchFake extends PendingBatch
{
/**
* The fake bus instance.
*
* @var \Illuminate\Support\Testing\Fakes\BusFake
*/
protected $bus;
/**
* Create a new pending batch instance.
*
* @param \Illuminate\Support\Testing\Fakes\BusFake $bus
* @param \Illuminate\Support\Collection $jobs
* @return void
*/
public function __construct(BusFake $bus, Collection $jobs)
{
$this->bus = $bus;
$this->jobs = $jobs;
}
/**
* Dispatch the batch.
*
* @return \Illuminate\Bus\Batch
*/
public function dispatch()
{
return $this->bus->recordPendingBatch($this);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Illuminate\Foundation\Bus\PendingChain;
use Illuminate\Queue\CallQueuedClosure;
class PendingChainFake extends PendingChain
{
/**
* The fake bus instance.
*
* @var \Illuminate\Support\Testing\Fakes\BusFake
*/
protected $bus;
/**
* Create a new pending chain instance.
*
* @param \Illuminate\Support\Testing\Fakes\BusFake $bus
* @param mixed $job
* @param array $chain
* @return void
*/
public function __construct(BusFake $bus, $job, $chain)
{
$this->bus = $bus;
$this->job = $job;
$this->chain = $chain;
}
/**
* Dispatch the job with the given arguments.
*
* @return \Illuminate\Foundation\Bus\PendingDispatch
*/
public function dispatch()
{
if (is_string($this->job)) {
$firstJob = new $this->job(...func_get_args());
} elseif ($this->job instanceof Closure) {
$firstJob = CallQueuedClosure::create($this->job);
} else {
$firstJob = $this->job;
}
$firstJob->allOnConnection($this->connection);
$firstJob->allOnQueue($this->queue);
$firstJob->chain($this->chain);
$firstJob->delay($this->delay);
$firstJob->chainCatchCallbacks = $this->catchCallbacks();
return $this->bus->dispatch($firstJob);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Mail\PendingMail;
class PendingMailFake extends PendingMail
{
/**
* Create a new instance.
*
* @param \Illuminate\Support\Testing\Fakes\MailFake $mailer
* @return void
*/
public function __construct($mailer)
{
$this->mailer = $mailer;
}
/**
* Send a new mailable message instance.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return void
*/
public function send(Mailable $mailable)
{
$this->mailer->send($this->fill($mailable));
}
/**
* Push the given mailable onto the queue.
*
* @param \Illuminate\Contracts\Mail\Mailable $mailable
* @return mixed
*/
public function queue(Mailable $mailable)
{
return $this->mailer->queue($this->fill($mailable));
}
}

View File

@@ -0,0 +1,461 @@
<?php
namespace Illuminate\Support\Testing\Fakes;
use BadMethodCallException;
use Closure;
use Illuminate\Contracts\Queue\Queue;
use Illuminate\Queue\QueueManager;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ReflectsClosures;
use PHPUnit\Framework\Assert as PHPUnit;
class QueueFake extends QueueManager implements Queue
{
use ReflectsClosures;
/**
* The original queue manager.
*
* @var \Illuminate\Contracts\Queue\Queue
*/
protected $queue;
/**
* The job types that should be intercepted instead of pushed to the queue.
*
* @var array
*/
protected $jobsToFake;
/**
* All of the jobs that have been pushed.
*
* @var array
*/
protected $jobs = [];
/**
* Create a new fake queue instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param array $jobsToFake
* @param \Illuminate\Queue\QueueManager|null $queue
* @return void
*/
public function __construct($app, $jobsToFake = [], $queue = null)
{
parent::__construct($app);
$this->jobsToFake = Collection::wrap($jobsToFake);
$this->queue = $queue;
}
/**
* Assert if a job was pushed based on a truth-test callback.
*
* @param string|\Closure $job
* @param callable|int|null $callback
* @return void
*/
public function assertPushed($job, $callback = null)
{
if ($job instanceof Closure) {
[$job, $callback] = [$this->firstClosureParameterType($job), $job];
}
if (is_numeric($callback)) {
return $this->assertPushedTimes($job, $callback);
}
PHPUnit::assertTrue(
$this->pushed($job, $callback)->count() > 0,
"The expected [{$job}] job was not pushed."
);
}
/**
* Assert if a job was pushed a number of times.
*
* @param string $job
* @param int $times
* @return void
*/
protected function assertPushedTimes($job, $times = 1)
{
$count = $this->pushed($job)->count();
PHPUnit::assertSame(
$times, $count,
"The expected [{$job}] job was pushed {$count} times instead of {$times} times."
);
}
/**
* Assert if a job was pushed based on a truth-test callback.
*
* @param string $queue
* @param string|\Closure $job
* @param callable|null $callback
* @return void
*/
public function assertPushedOn($queue, $job, $callback = null)
{
if ($job instanceof Closure) {
[$job, $callback] = [$this->firstClosureParameterType($job), $job];
}
$this->assertPushed($job, function ($job, $pushedQueue) use ($callback, $queue) {
if ($pushedQueue !== $queue) {
return false;
}
return $callback ? $callback(...func_get_args()) : true;
});
}
/**
* Assert if a job was pushed with chained jobs based on a truth-test callback.
*
* @param string $job
* @param array $expectedChain
* @param callable|null $callback
* @return void
*/
public function assertPushedWithChain($job, $expectedChain = [], $callback = null)
{
PHPUnit::assertTrue(
$this->pushed($job, $callback)->isNotEmpty(),
"The expected [{$job}] job was not pushed."
);
PHPUnit::assertTrue(
collect($expectedChain)->isNotEmpty(),
'The expected chain can not be empty.'
);
$this->isChainOfObjects($expectedChain)
? $this->assertPushedWithChainOfObjects($job, $expectedChain, $callback)
: $this->assertPushedWithChainOfClasses($job, $expectedChain, $callback);
}
/**
* Assert if a job was pushed with an empty chain based on a truth-test callback.
*
* @param string $job
* @param callable|null $callback
* @return void
*/
public function assertPushedWithoutChain($job, $callback = null)
{
PHPUnit::assertTrue(
$this->pushed($job, $callback)->isNotEmpty(),
"The expected [{$job}] job was not pushed."
);
$this->assertPushedWithChainOfClasses($job, [], $callback);
}
/**
* Assert if a job was pushed with chained jobs based on a truth-test callback.
*
* @param string $job
* @param array $expectedChain
* @param callable|null $callback
* @return void
*/
protected function assertPushedWithChainOfObjects($job, $expectedChain, $callback)
{
$chain = collect($expectedChain)->map(fn ($job) => serialize($job))->all();
PHPUnit::assertTrue(
$this->pushed($job, $callback)->filter(fn ($job) => $job->chained == $chain)->isNotEmpty(),
'The expected chain was not pushed.'
);
}
/**
* Assert if a job was pushed with chained jobs based on a truth-test callback.
*
* @param string $job
* @param array $expectedChain
* @param callable|null $callback
* @return void
*/
protected function assertPushedWithChainOfClasses($job, $expectedChain, $callback)
{
$matching = $this->pushed($job, $callback)->map->chained->map(function ($chain) {
return collect($chain)->map(function ($job) {
return get_class(unserialize($job));
});
})->filter(function ($chain) use ($expectedChain) {
return $chain->all() === $expectedChain;
});
PHPUnit::assertTrue(
$matching->isNotEmpty(), 'The expected chain was not pushed.'
);
}
/**
* Determine if the given chain is entirely composed of objects.
*
* @param array $chain
* @return bool
*/
protected function isChainOfObjects($chain)
{
return ! collect($chain)->contains(fn ($job) => ! is_object($job));
}
/**
* Determine if a job was pushed based on a truth-test callback.
*
* @param string|\Closure $job
* @param callable|null $callback
* @return void
*/
public function assertNotPushed($job, $callback = null)
{
if ($job instanceof Closure) {
[$job, $callback] = [$this->firstClosureParameterType($job), $job];
}
PHPUnit::assertCount(
0, $this->pushed($job, $callback),
"The unexpected [{$job}] job was pushed."
);
}
/**
* Assert that no jobs were pushed.
*
* @return void
*/
public function assertNothingPushed()
{
PHPUnit::assertEmpty($this->jobs, 'Jobs were pushed unexpectedly.');
}
/**
* Get all of the jobs matching a truth-test callback.
*
* @param string $job
* @param callable|null $callback
* @return \Illuminate\Support\Collection
*/
public function pushed($job, $callback = null)
{
if (! $this->hasPushed($job)) {
return collect();
}
$callback = $callback ?: fn () => true;
return collect($this->jobs[$job])->filter(
fn ($data) => $callback($data['job'], $data['queue'], $data['data'])
)->pluck('job');
}
/**
* Determine if there are any stored jobs for a given class.
*
* @param string $job
* @return bool
*/
public function hasPushed($job)
{
return isset($this->jobs[$job]) && ! empty($this->jobs[$job]);
}
/**
* Resolve a queue connection instance.
*
* @param mixed $value
* @return \Illuminate\Contracts\Queue\Queue
*/
public function connection($value = null)
{
return $this;
}
/**
* Get the size of the queue.
*
* @param string|null $queue
* @return int
*/
public function size($queue = null)
{
return collect($this->jobs)->flatten(1)->filter(
fn ($job) => $job['queue'] === $queue
)->count();
}
/**
* Push a new job onto the queue.
*
* @param string|object $job
* @param mixed $data
* @param string|null $queue
* @return mixed
*/
public function push($job, $data = '', $queue = null)
{
if ($this->shouldFakeJob($job)) {
$this->jobs[is_object($job) ? get_class($job) : $job][] = [
'job' => $job,
'queue' => $queue,
'data' => $data,
];
} else {
is_object($job) && isset($job->connection)
? $this->queue->connection($job->connection)->push($job, $data, $queue)
: $this->queue->push($job, $data, $queue);
}
}
/**
* Determine if a job should be faked or actually dispatched.
*
* @param object $job
* @return bool
*/
public function shouldFakeJob($job)
{
if ($this->jobsToFake->isEmpty()) {
return true;
}
return $this->jobsToFake->contains(
fn ($jobToFake) => $job instanceof ((string) $jobToFake)
);
}
/**
* Push a raw payload onto the queue.
*
* @param string $payload
* @param string|null $queue
* @param array $options
* @return mixed
*/
public function pushRaw($payload, $queue = null, array $options = [])
{
//
}
/**
* Push a new job onto the queue after (n) seconds.
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @param string|object $job
* @param mixed $data
* @param string|null $queue
* @return mixed
*/
public function later($delay, $job, $data = '', $queue = null)
{
return $this->push($job, $data, $queue);
}
/**
* Push a new job onto the queue.
*
* @param string $queue
* @param string|object $job
* @param mixed $data
* @return mixed
*/
public function pushOn($queue, $job, $data = '')
{
return $this->push($job, $data, $queue);
}
/**
* Push a new job onto a specific queue after (n) seconds.
*
* @param string $queue
* @param \DateTimeInterface|\DateInterval|int $delay
* @param string|object $job
* @param mixed $data
* @return mixed
*/
public function laterOn($queue, $delay, $job, $data = '')
{
return $this->push($job, $data, $queue);
}
/**
* Pop the next job off of the queue.
*
* @param string|null $queue
* @return \Illuminate\Contracts\Queue\Job|null
*/
public function pop($queue = null)
{
//
}
/**
* Push an array of jobs onto the queue.
*
* @param array $jobs
* @param mixed $data
* @param string|null $queue
* @return mixed
*/
public function bulk($jobs, $data = '', $queue = null)
{
foreach ($jobs as $job) {
$this->push($job, $data, $queue);
}
}
/**
* Get the jobs that have been pushed.
*
* @return array
*/
public function pushedJobs()
{
return $this->jobs;
}
/**
* Get the connection name for the queue.
*
* @return string
*/
public function getConnectionName()
{
//
}
/**
* Set the connection name for the queue.
*
* @param string $name
* @return $this
*/
public function setConnectionName($name)
{
return $this;
}
/**
* Override the QueueManager to prevent circular dependency.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
throw new BadMethodCallException(sprintf(
'Call to undefined method %s::%s()', static::class, $method
));
}
}