Git Product home page Git Product logo

Comments (6)

samarjaffal avatar samarjaffal commented on June 7, 2024 2

Sorry, I didn't answer your reply. I just want to tell you that I did get it work! Thanks a lot for your help!

from arcanist.

michaelklopf avatar michaelklopf commented on June 7, 2024

Hey,

we test two parts. The individual steps and the onCompleteAction.

When the wizard completes it runs this code

        $result = $this->actionResolver
            ->resolveAction($this->onCompleteAction)
            ->execute($this->transformWizardData($request));

So we have an action that has the following signature:

<?php

namespace /* namespace */;

/* imports here */

final class SaveMyObject extends WizardAction
{
    public function __construct(
        public DoSomethingAction $doSomethingAction,
        public DoMoreAction $doMoreAction
    ) {
    }

    public function execute(mixed $payload): ActionResult
    {
        $object_you_want = DB::transaction(function () use ($payload) {
            $object_you_want = $this->doSomethingAction->execute($payload); // our own actions, we adapt the techniques from Laravel Beyond Crud
            $this->doMoreAction->execute($payload);

            return $object_you_want;
        });

        return $this->success(['object_id' => $object_you_want->id]);
    }
}

Now in the test you can mock your actions and check they are called and you get returned what you expect

    /** @test */
    public function it_creates_my_object()
    {
        Storage::fake('minio');

        $payload = [
            'a_date' => '2021-01-01',
            'attribute_value' => 'foo',
            'stuff' => 'bar',
            'an_array' => [
                'content' => '<p>Example content</p>',
            ],
        ];

        $this->mock(DoSomethingAction::class, function (MockInterface $mock) {
            $mock->shouldReceive('execute')
                ->once()->andReturn(MyObject::factory()->create());
        });

        $this->mock(DoMoreAction::class, function (MockInterface $mock) {
            $mock->shouldReceive('execute')
                ->once();
        });

        $this->action = app(SaveMyObject::class);
        $result = $this->action->execute($payload);

        $this->assertInstanceOf(ActionResult::class, $result);

        $my_object = MyObject::first();

        $this->assertEquals($result->get('object_id'), $my_object->id);
    }

Or you simply let the code run through and assert everything you want here. The payload is not necessary in this example but I adapted from our code and didn't want to change everything.

And then there is testing individual steps. In the setup you create an instance of the wizard. We assume this is step 3 of many.

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

        $this->wizardId = Wizard::create([
            'class' => MyObjectWizard::class,
            'data' => [
                'important_value' => AnotherObject::factory()->create()->id,
                '_arcanist' => [
                    'step_1' => true,
                    'step_2' => true,
                ],
            ],
        ])->id;

        Passport::actingAs(User::factory()->wizardOfOz()->create());
    }

And in the test you can assert if the wizard uses the correct fields.

    /** @test */
    public function returning_the_correct_fields()
    {
        $fields = $this->get(
            route('wizard.my-object.show', [
                'wizardId' => $this->wizardId,
                'slug' => 'type_value',
            ])
        )->json('fields');

        $used_fields = collect($fields)->mapWithKeys(fn ($field) => [
            $field['name'] => $field['component'],
        ])->all();

        $this->assertEquals(
            [
                'a_date' => 'Date',
                'attribute_value' => 'Text',
                'something_else' => 'Select',
                'stuff' => 'Text',
                'money' => 'Currency',
                'an_array' => 'CheckboxGroup',
            ],
            $used_fields
        );
    }

Or if the validation is correct

        $this->withExceptionHandling()
            ->postJson(
                route('wizard.my-object.update', [
                    'wizardId' => $this->wizardId,
                    'slug' => 'type_value',
                ]),
                [ 'stuff' => null ]
            )
            ->assertStatus(422)
            ->assertJsonValidationErrors('stuff');

I don't know if this helps, but maybe someone needs a starting point or seeing it done wrong 😬

from arcanist.

samarjaffal avatar samarjaffal commented on June 7, 2024

Hi, I have problems when I try to make a test for the wizard. Do you have other examples? I want to test a Wizard that I had created and the steps for the wizard. I'll appreciate the help on this. Thanks

from arcanist.

michaelklopf avatar michaelklopf commented on June 7, 2024

Well, you can post your code with markdown code tags here and we can see if we can help you. I have no other kind of test. I either test the completion of the wizard or the steps as described above.

from arcanist.

samarjaffal avatar samarjaffal commented on June 7, 2024

The problem is when I test step with your code, it's giving me 404 not found.
here->> $this->get(route('route_name'));

But if I check if the route exists, the result is true. So, I don't know if I'm missing something.

from arcanist.

michaelklopf avatar michaelklopf commented on June 7, 2024

I can duplicate the error, when I use a wizardId that doesn't exist in the route helper.

        $fields = $this->get(
            route('wizard.my-object.show', [
                'wizardId' => '20000',
                'slug' => 'slug_value',
            ])
        )->json('fields');

So maybe

        $this->wizardId = Wizard::create([
            'class' => MyObjectWizard::class,
            'data' => [
                'important_value' => AnotherObject::factory()->create()->id,
                '_arcanist' => [
                    'slug_value_1' => true,
                    'slug_value_2' => true,
                ],
            ],
        ])->id;

didn't return the correct wizard for you?

Namespace use Arcanist\Repository\Wizard; is correct for the Wizard? You need to pay attention to the slug_value values in the _arcanist part. They say that the previous steps are done. In the first step the _arcanist array can be left out.

                '_arcanist' => [
                    'step_1' => true,
                    'step_2' => true,
                ],

Maybe try for a simple check if this works, because when setting up the test you have only one wizard in the db which has ID 1.

        $fields = $this->get(
            route('wizard.my-object.show', [
                'wizardId' => '1',
                'slug' => 'slug_value',
            ])
        )->json('fields');

Oh, and another thing that could be a problem is if the use RefreshDatabase; trait is missing on the test case.

Other stuff I wrote first:

Check if the route helper is returning the wrong route. Either dump() it and check against php artisan route:list or instead of the route helper call the route directly with

$fields = $this->get(
            '/api/arcanist/wizards/my-object/'.$this->wizardId.'/type_value'
        )->json('fields')

The part api/arcanist/wizards is taken from the arcanist config

    'route_prefix' => 'api/assign/wizards',

404 error usually means that something went wrong in the test with calling the correct route or the setup of the app.

from arcanist.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.