Skip to content

Commit

Permalink
Merge branch 'production' of github.com:christophrumpel/missing-livew…
Browse files Browse the repository at this point in the history
…ire-assertions into production
  • Loading branch information
christophrumpel committed Mar 26, 2024
2 parents dd219ba + 5da3c0e commit a960bf7
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .php-cs-fixer.cache
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"php":"8.3.4","version":"3.51.0","indent":" ","lineEnding":"\n","rules":{"blank_line_after_namespace":true,"braces_position":true,"class_definition":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline","keep_multiple_spaces_after_comma":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":{"elements":["method","property"]},"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"ordered_imports":{"sort_algorithm":"alpha"},"no_unused_imports":true,"not_operator_with_successor_space":true,"trailing_comma_in_multiline":true,"phpdoc_scalar":true,"unary_operator_spaces":true,"binary_operator_spaces":true,"blank_line_before_statement":{"statements":["break","continue","declare","return","throw","try"]},"phpdoc_single_line_var_spacing":true,"phpdoc_var_without_name":true,"class_attributes_separation":{"elements":{"const":"one","method":"one","property":"one"}},"single_trait_insert_per_statement":true},"hashes":{"src\/ComponentName.php":"af0dc94880495710238f36e09974f56b","src\/MissingLivewireAssertionsServiceProvider.php":"001e0571136e8126eb93c4ddb1bbb53a","src\/CustomLivewireAssertionsMixin.php":"22184762d22411af16d2498a3f5e31b8","tests\/resources\/views\/livewire-test-component-a.php":"42c308f0b6f9578b688100a9a925f550","tests\/resources\/views\/livewire-test-component-b.php":"ab1e1d7326d9e0a269a84c239503d679","tests\/resources\/views\/livewire-test-component-c.php":"6aef47d3280960b92b464e77db3063c2","tests\/resources\/views\/blade-test-component.php":"4b61e7dba267eb48b3fa25a14e0d086b","tests\/AssertionsTest.php":"85b24f7379c231b96776e7cd81e9631b","tests\/Components\/FileDownloadComponent.php":"92f6b79d4253193dc1503a0d84d6ac7e","tests\/Components\/LivewireTestComponentA.php":"2306729210f9134b92a46d05c71dc566","tests\/Components\/LivewireTestComponentC.php":"d516104cd3b4eb72826b8a3eef9246fd","tests\/Components\/LivewireTestComponentB.php":"7ef74a34799d9cc730a738f40eeb2b40","tests\/View\/Components\/Button.php":"ed586764f2469ec4b6a76d0f0d96f6ba","tests\/TestCase.php":"d1c940f002919088c735f0ced367b898"}}
{"php":"8.3.4","version":"3.51.0","indent":" ","lineEnding":"\n","rules":{"blank_line_after_namespace":true,"braces_position":true,"class_definition":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline","keep_multiple_spaces_after_comma":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"visibility_required":{"elements":["method","property"]},"encoding":true,"full_opening_tag":true,"array_syntax":{"syntax":"short"},"ordered_imports":{"sort_algorithm":"alpha"},"no_unused_imports":true,"not_operator_with_successor_space":true,"trailing_comma_in_multiline":true,"phpdoc_scalar":true,"unary_operator_spaces":true,"binary_operator_spaces":true,"blank_line_before_statement":{"statements":["break","continue","declare","return","throw","try"]},"phpdoc_single_line_var_spacing":true,"phpdoc_var_without_name":true,"class_attributes_separation":{"elements":{"const":"one","method":"one","property":"one"}},"single_trait_insert_per_statement":true},"hashes":{"src\/ComponentName.php":"af0dc94880495710238f36e09974f56b","src\/MissingLivewireAssertionsServiceProvider.php":"001e0571136e8126eb93c4ddb1bbb53a","src\/CustomLivewireAssertionsMixin.php":"0e964fa3412324abaa6c443be65b6030","tests\/resources\/views\/livewire-test-component-a.php":"42c308f0b6f9578b688100a9a925f550","tests\/resources\/views\/livewire-test-component-b.php":"ab1e1d7326d9e0a269a84c239503d679","tests\/resources\/views\/livewire-test-component-c.php":"b91a9c12dd35893f20ffc42f92bfb68e","tests\/resources\/views\/blade-test-component.php":"4b61e7dba267eb48b3fa25a14e0d086b","tests\/AssertionsTest.php":"15f3ed6d76e30db8b307a458b9a20d10","tests\/Components\/FileDownloadComponent.php":"92f6b79d4253193dc1503a0d84d6ac7e","tests\/Components\/LivewireTestComponentA.php":"2306729210f9134b92a46d05c71dc566","tests\/Components\/LivewireTestComponentC.php":"d516104cd3b4eb72826b8a3eef9246fd","tests\/Components\/LivewireTestComponentB.php":"7ef74a34799d9cc730a738f40eeb2b40","tests\/View\/Components\/Button.php":"ed586764f2469ec4b6a76d0f0d96f6ba","tests\/TestCase.php":"d1c940f002919088c735f0ced367b898","tests\/resources\/views\/livewire-test-component-d.php":"5316f158439e7e01c467a5ac16508dd1","tests\/Components\/LivewireTestComponentD.php":"a0a14bddb133c4a7e971b6d3c31d3d0e"}}
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ Livewire::test(FeedbackForm::class)
->assertMethodWired('$toggle(\'sortAsc\')');
```

### Check if a generic Livewire method is wired to an HTML field

```php
Livewire::test(FeedbackForm::class)
->assertMethodWiredToAction('mouseenter', 'enter');
```

It looks for a string like `wire:mouseenter="enter"` in your component's view file. Also, note that it can also look for any events, like `wire:keydown` or `wire:custom-event`.

It looks for a string like `wire:click="$refresh"`, `wire:click="$toggle('sortAsc')`, `$dispatch('post-created')`, along with all other [magic actions](https://livewire.laravel.com/docs/actions#magic-actions). When testing for magic actions, you must escape single quotes like shown above.

### Check if a Livewire method is wired to an HTML form
Expand Down
32 changes: 31 additions & 1 deletion src/CustomLivewireAssertionsMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,36 @@ public function assertMethodNotWired(): Closure
};
}

/**
* Assert that the given method is wired to a generic method.
*/
public function assertMethodWiredToAction(): Closure
{
return function (string $methodName, string $action) {
PHPUnit::assertMatchesRegularExpression(
'/wire:' . $methodName . '?=(?<q>"|\')'.preg_quote($action).'(\s*\(.+\)\s*)?\s*(\k\'q\')/',
$this->html()
);

return $this;
};
}

/**
* Assert that the given method is NOT wired to a generic method.
*/
public function assertMethodNotWiredToAction(): Closure
{
return function (string $methodName, string $action) {
PHPUnit::assertDoesNotMatchRegularExpression(
'/wire:' . $methodName . '?=(?<q>"|\')'.preg_quote($action).'(\s*\(.+\)\s*)?\s*(\k\'q\')/',
$this->html()
);

return $this;
};
}

/**
* Assert that the given method is wired to form
*/
Expand Down Expand Up @@ -221,7 +251,7 @@ public function assertContainsLivewireComponent(): Closure
$componentHaystackView = file_get_contents($this->lastState->getView()->getPath());

PHPUnit::assertMatchesRegularExpression(
'/@livewire\(\''.$component.'\'|<livewire\:'.$component.'/',
'/@livewire\(\s*\''.$component.'\'|<livewire\:'.$component.'/',
$componentHaystackView
);

Expand Down
53 changes: 53 additions & 0 deletions tests/AssertionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Tests\Components\LivewireTestComponentA;
use Tests\Components\LivewireTestComponentB;
use Tests\Components\LivewireTestComponentC;
use Tests\Components\LivewireTestComponentD;
use Tests\View\Components\Button;

class AssertionsTest extends TestCase
Expand Down Expand Up @@ -113,6 +114,57 @@ public function it_checks_if_livewire_method_is_not_wired_with_params_to_a_field
->assertMethodNotWired('preventParams_not_wired');
}

/** @test * */
public function it_checks_if_a_generic_livewire_method_is_wired_to_a_field(): void
{
Livewire::test(LivewireTestComponentD::class)
->assertMethodWiredToAction('change', 'change')
->assertMethodWiredToAction('keydown', 'keydown')
->assertMethodWiredToAction('keyup', 'keyup')
->assertMethodWiredToAction('mouseenter', 'mouseEnter')
->assertMethodWiredToAction('keydown.enter', 'keyDownEnter')
->assertMethodWiredToAction('keydown.shift.enter', 'keyDownShiftEnterMethod')
->assertMethodWiredToAction('transitionend', 'transitionendMethod')
->assertMethodWiredToAction('custom-event', 'customEventMethod')
->assertMethodWiredToAction('change', 'singlequote')
->assertMethodWiredToAction('mouseenter', '$toggle(\'sortAsc\')')
->assertMethodWiredToAction('mouseenter', '$dispatch(\'post-created\')')
->assertMethodWiredToAction('mouseenter', 'search($event.target.value)')
->assertMethodWiredToAction('mouseenter', '$wire.$refresh()')
->assertMethodWiredToAction('mouseenter', '$parent.removePost({{ $post->id }})')
->assertMethodWiredToAction('mouseenter', '$set(\'query\', \'\')')
;
}

/** @test * */
public function it_checks_if_a_generic_livewire_method_is_not_wired_to_a_field(): void
{
Livewire::test(LivewireTestComponentD::class)
->assertMethodNotWiredToAction('change', 'change_not_wired')
->assertMethodNotWiredToAction('keydown', 'keydown_not_wired')
->assertMethodNotWiredToAction('keyup', 'keyup_not_wired')
->assertMethodNotWiredToAction('mouseenter', 'mouseEnter_not_wired')
->assertMethodNotWiredToAction('keydown.enter', 'keyDownEnter_not_wired')
->assertMethodNotWiredToAction('keydown.shift.enter', 'keyDownShiftEnterMethod_not_wired')
->assertMethodNotWiredToAction('transitionend', 'transitionendMethod_not_wired')
->assertMethodNotWiredToAction('custom-event', 'customEventMethod_not_wired')
;
}

/** @test * */
public function it_checks_if_a_generic_livewire_method_is_wired_with_params_to_a_field()
{
Livewire::test(LivewireTestComponentD::class)
->assertMethodWiredToAction('mouseenter', 'params');
}

/** @test * */
public function it_checks_if_a_generic_livewire_method_is_not_wired_with_params_to_a_field()
{
Livewire::test(LivewireTestComponentD::class)
->assertMethodNotWiredToAction('mouseenter', 'params_not_wired');
}

/** @test * */
public function it_checks_if_livewire_method_is_wired_to_a_form(): void
{
Expand Down Expand Up @@ -288,6 +340,7 @@ public function it_checks_if_it_does_not_see_string_before_other_string(): void
public function it_checks_if_it_sees_a_blade_directive(): void
{
Livewire::test(LivewireTestComponentC::class)
->assertContainsLivewireComponent(LivewireTestComponentA::class)
->assertContainsLivewireComponent(LivewireTestComponentB::class);
}

Expand Down
13 changes: 13 additions & 0 deletions tests/Components/LivewireTestComponentD.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Tests\Components;

use Livewire\Component;

class LivewireTestComponentD extends Component
{
public function render()
{
return view('livewire-test-component-d');
}
}
5 changes: 4 additions & 1 deletion tests/resources/views/livewire-test-component-c.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<div>
@livewire('tests.components.livewire-test-component-b')
@livewire('tests.components.livewire-test-component-a')
@livewire(
'tests.components.livewire-test-component-b'
)
</div>
21 changes: 21 additions & 0 deletions tests/resources/views/livewire-test-component-d.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div>
<input type="text" wire:change="change" />
<input type="text" wire:keydown="keydown" />
<input type="text" wire:keyup="keyup" />
<input type="text" wire:mouseenter="mouseEnter" />
<input type="text" wire:keydown.enter="keyDownEnter" />
<input type="text" wire:keydown.shift.enter="keyDownShiftEnterMethod" />
<input type="text" wire:transitionend="transitionendMethod" />
<input type="text" wire:custom-event="customEventMethod" />
<input type="text" wire:change='singlequote' />
<x-button wire:mouseenter="submit" />
<x-button wire:mouseenter="$refresh" />
<x-button wire:mouseenter="$toggle('sortAsc')" />
<x-button wire:mouseenter="$dispatch('post-created')" />
<x-button wire:mouseenter="search($event.target.value)" />
<x-button wire:mouseenter="$wire.$refresh()" />
<x-button wire:mouseenter="$parent.removePost({{ $post->id }})" />
<x-button wire:mouseenter="$set('query', '')" />
<x-button wire:mouseenter="params({{$prop}}, 42)" />
</div>

0 comments on commit a960bf7

Please sign in to comment.