anuzpandey's avatar

How to Test Custom Macros in PEST?

Hello. I have created a custom macro for my class using a Macroable trait that laravel provides. If I test the same thing in Tinkerwell or in the browser. I get the expected result and everything works. But on the test, its giving me error.

it('ensures the getSizeValue Macro is present', function (): void {
    expect(RudrakshaFace::hasMacro('getSizeValue'))->toBeTrue();
});

it('ensures ...', function ($range, $value, $expectedResult): void {
    $sizeRange = $range;
    $result = RudrakshaFace::getSizeValue($value, $sizeRange);

    expect($result)
        ->toBe($expectedResult);
})->with([
    [['Re' => '<19', 'Me' => '19-20', 'Co' => '21-22'], 12, 'Re'],
]);

Thank you in advance.

0 likes
9 replies
tykus's avatar

What error is it giving you?

Aside, if you own RudrakshaFace, then why do you need a macro at all?

anuzpandey's avatar

@tykus The error is while running test. hasMacro('getSizeValue') is false, which when I run on the Tinkerwell its true as it is present. Yes I own the RudrakshaFace for now but, we are converting this part to a package later so its needed (I guess its better to have.)

tykus's avatar

@anuzpandey is this a Feature test or a Unit test - if it is not a Feature test, you are not booting the Framework (and registering the macro etc.)?

anuzpandey's avatar

@tykus I tried adding it to the Feature Test as well. But didn't work out. RudrakshaFace is a model so I guess adding a Macroable trait within the Model itself doesn't work. It did work for most part in the application, but create and other eloquent functions were not working. So I refactored the method to Model class (RudrakshaFace) as a static function. And I don't know (but I think) its not good idea to add Macroable Trait inside a Model Class. If it's doable and is considered a thing we can do. Please let me know...

tykus's avatar
tykus
Best Answer
Level 104

@anuzpandey again, I don't know why you need to make your Model macroable at all? Is this part of a package that would allow others to extend your model?

A problem I see with using Macroable on a Model class is the __call and __callStatic magic methods are defined in both the trait and in the base Model class. The trait's definition will take precedence over the base class' method which will break a lot of Eloquent behaviours.

So no, using Macroable on a Model is not a good idea!

anuzpandey's avatar

@tykus Yeah. While performing the eloquent functions, application broke. So, yes. Im removing macro stuffs from Model class.

Initially I thought. many things can be added to Model class and being within a package, wont allow other to customize. So I tried giving all the features :E I could. So now, like Spatie does, in config I added the option to opt in their own model and extend the base Model and add their stuffs. And Removed Macroable stuffs.

Thank you for the clarification too.

anuzpandey's avatar

@tykus But Still how do we test custom Macro that we register in our application. I have a custom macro for Illuminate\Support\Str class. Str::toNepali(123). This runs okay. But in test, it says Illuminate\Support\Str::toNepali does not exists. You said something about booting the application, am I missing something here...?

tykus's avatar

@anuzpandey it should work in a Feature test since the framework is booted as part of the setup (unlike a Unit test). Can you tell me where you are registering the macro(s) on these macroable classes?

anuzpandey's avatar

@tykus So, I have a MacroableServiceProvider

class MacroableServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Str::mixin(new StrMixin());
        Blueprint::mixin(new BlueprintMixin());
        Collection::mixin(new CollectionMixin());
        URL::mixin(new URLMixin());
        Command::mixin(new CommandMixin());
    }
}

And, I have registered it to the config\app.php,

'providers' => ServiceProvider::defaultProviders()->merge([
    // Other Providers ...

    // Custom Providers...
    App\Providers\MacroableServiceProvider::class,
    App\Providers\BladeDirectiveServiceProvider::class,
])->toArray(),

My test Feature\Macro\Mixin\StrMixinTest.php

it('ensures toNepali method exists in Str Class from mixin', function (): void {
    expect(\Illuminate\Support\Str::hasMacro('toNepali'))->toBeTrue();
});

Please or to participate in this conversation.