lorisleiva / laravel-actions

⚡️ Laravel components that take care of one specific task
https://laravelactions.com
MIT License
2.41k stars 117 forks source link

assertChained not working with actions #236

Open HugoHeneault opened 1 year ago

HugoHeneault commented 1 year ago

Hi there! Using actions for awhile, thanks for this great plugin 🙌

We're chaining actions but assertChained isn't working :

  1. ProcessActivityJob is a normal ShouldQueue implementation.
  2. UpdateUserParticipationsOnChallenges uses AsAction
  3. CreateMyActivity chains this two jobs.

When UpdateUserParticipationsOnChallenges is a ShouldQueue implementation assertChained works. If we're using it only as an action, it fails.

Here's some code:

Our test:


    // Processing action
    CreateMyActivity::run($data, $this->user);

    // This is true
    Bus::assertDispatched(ProcessActivityJob::class);

    // fails
    Bus::assertChained([
        ProcessActivityJob::class,
        UpdateUserParticipationsOnChallenges::class,
    ]);

Here're BusFake implem:

I think the problem is BusFake uses return get_class(unserialize($job)); to get the chainName I don't see how we could fix it? Of course we can use a normal ShouldQueue implem but it makes us create another class, we'de prefer not to.

    /**
     * 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(
                function ($job) {
                    return get_class(unserialize($job));
                }
            );
        })->filter(
            function ($chain) use ($command, $expectedChain, $callback) {
                $chainName = $chain->all() === $expectedChain;

               // here chainName is `Lorisleiva\Actions\Decorators\JobDecorator` and not our chained class, so it fails
                return $chainName;
            }
        );

        PHPUnit::assertTrue(
            $matching->isNotEmpty(), 'The expected chain was not dispatched.'
        );
    }

Thanks for your help!

edalzell commented 1 year ago

I just did this, you have to actually put the job decorator in your test like so:

CleanShot 2023-07-27 at 16 39 45@2x
poldixd commented 2 months ago

I just did this, you have to actually put the job decorator in your test like so: CleanShot 2023-07-27 at 16 39 45@2x

I have the same issue. How do you dispatch the bus chain?

edalzell commented 2 months ago

CleanShot 2024-05-07 at 13 22 19@2x