From df4ef9a54483d3ae2e200d75d42996da1e12b8eb Mon Sep 17 00:00:00 2001 From: bzy107 Date: Tue, 25 Feb 2025 23:29:50 +0900 Subject: [PATCH 01/12] feat: add queryBuilder test --- packages/tables/.stubs.php | 2 + packages/tables/src/TablesServiceProvider.php | 2 + .../tables/src/Testing/TestsQueryBuilders.php | 63 ++++++++ tests/src/Tables/Filters/QueryBuilderTest.php | 142 ++++++++++++++++++ .../Fixtures/PostsQueryBuilderTable.php | 53 +++++++ 5 files changed, 262 insertions(+) create mode 100644 packages/tables/src/Testing/TestsQueryBuilders.php create mode 100644 tests/src/Tables/Filters/QueryBuilderTest.php create mode 100644 tests/src/Tables/Fixtures/PostsQueryBuilderTable.php diff --git a/packages/tables/.stubs.php b/packages/tables/.stubs.php index aca33e01afb..75936ad031c 100644 --- a/packages/tables/.stubs.php +++ b/packages/tables/.stubs.php @@ -177,6 +177,8 @@ public function assertCanSeeTableRecords(array | Collection $records, bool $inOr public function assertCanNotSeeTableRecords(array | Collection $records): static {} + public function queryBuilderTable(string $column, string $operator, $data = null): static {} + public function assertCountTableRecords(int $count): static {} public function loadTable(): static {} diff --git a/packages/tables/src/TablesServiceProvider.php b/packages/tables/src/TablesServiceProvider.php index ecdb8b4ad85..52fbc6f9e15 100644 --- a/packages/tables/src/TablesServiceProvider.php +++ b/packages/tables/src/TablesServiceProvider.php @@ -8,6 +8,7 @@ use Filament\Tables\Testing\TestsBulkActions; use Filament\Tables\Testing\TestsColumns; use Filament\Tables\Testing\TestsFilters; +use Filament\Tables\Testing\TestsQueryBuilders; use Filament\Tables\Testing\TestsRecords; use Filament\Tables\Testing\TestsSummaries; use Illuminate\Filesystem\Filesystem; @@ -44,6 +45,7 @@ public function packageBooted(): void Testable::mixin(new TestsBulkActions); Testable::mixin(new TestsColumns); Testable::mixin(new TestsFilters); + Testable::mixin(new TestsQueryBuilders); Testable::mixin(new TestsRecords); Testable::mixin(new TestsSummaries); } diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php new file mode 100644 index 00000000000..9c6489e8ed5 --- /dev/null +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -0,0 +1,63 @@ +assertTableConstraintExists($column); + + $constraint = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($column); + + if ($constraint instanceof TextConstraint) { + $queryBuilder = [ + 'type' => $column, + 'data' => [ + 'operator' => $operator, + 'settings' => [], + ] + ]; + + if ($data) { + $queryBuilder['data']['settings'] = ['text' => $data]; + } + } + + $this->set("tableFilters.queryBuilder.rules.{$constraint->getName()}", $queryBuilder); + + return $this; + }; + } + + public function assertTableConstraintExists(): Closure + { + return function (string $column): static { + $filter = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($column); + + $livewireClass = $this->instance()::class; + + Assert::assertInstanceOf( + Constraint::class, + $filter, + message: "Failed asserting that a table filter with name [{$column}] exists on the [{$livewireClass}] component.", + ); + + return $this; + }; + } +} diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php new file mode 100644 index 00000000000..48b0458a02f --- /dev/null +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -0,0 +1,142 @@ +create(); + $content = $posts->random()->content; + $filter = substr($content, 2, 7); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'contains', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'like', '%' . $filter . '%')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter . '%')->get()); +}); + +it('can filter text constraint for `not contains`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + $filter = substr($content, 2, 7); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'contains.inverse', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'not like', '%' . $filter . '%')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'like', '%' . $filter . '%')->get()); +}); + +it('can filter text constraint for `startsWith`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + $filter = substr($content, 0, 5); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'startsWith', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'like', $filter . '%')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'not like', $filter . '%')->get()); +}); + +it('can filter text constraint for `not startsWith`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + $filter = substr($content, 0, 5); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'startsWith.inverse', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'not like', $filter . '%')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'like', $filter . '%')->get()); +}); + +it('can filter text constraint for `endsWith`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + $filter = substr($content, -5); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'endsWith', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'like', '%' . $filter)->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter)->get()); +}); + +it('can filter text constraint for `not endsWith`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + $filter = substr($content, -5); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'endsWith.inverse', $filter) + ->assertCanSeeTableRecords(Post::where('content', 'not like', '%' . $filter)->get()) + ->assertCanNotSeeTableRecords(Post::where('content', 'like', '%' . $filter)->get()); +}); + +it('can filter text constraint for `equals`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'equals', $content) + ->assertCanSeeTableRecords(Post::where('content', $content)->get()) + ->assertCanNotSeeTableRecords(Post::where('content', '<>', $content)->get()); +}); + +it('can filter text constraint for `not equals`', function () { + $posts = Post::factory(10)->create(); + $content = $posts->random()->content; + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'equals.inverse', $content) + ->assertCanSeeTableRecords(Post::where('content', '<>', $content)->get()) + ->assertCanNotSeeTableRecords(Post::where('content', $content)->get()); +}); + +it('can filter text constraint for `isFilled`', function () { + Post::factory(8)->create(); + Post::factory()->create(['content' => null]); + Post::factory()->create(['content' => '']); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords(Post::all()) + ->queryBuilderTable('content', 'isFilled') + ->assertCanSeeTableRecords(Post::where('content', '<>', null)->where('content', '<>', '')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', null)->orWhere('content', '')->get()); +}); + +it('can filter text constraint for `not isFilled`', function () { + Post::factory(8)->create(); + Post::factory()->create(['content' => null]); + Post::factory()->create(['content' => '']); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords(Post::all()) + ->queryBuilderTable('content', 'isFilled.inverse') + ->assertCanSeeTableRecords(Post::where('content', null)->orWhere('content', '')->get()) + ->assertCanNotSeeTableRecords(Post::where('content', '<>', null)->where('content', '<>', '')->get()); +}); + +// it('can filter records by text constraint in the query builder with modal action', function () { +// $posts = Post::factory()->count(10)->create(); +// $content = $posts->first()->content; +// $post = Post::where('content', $content); + +// livewire(PostsQueryBuilderTable::class) +// ->assertCanSeeTableRecords($posts) +// ->queryBuilderTable('content', 'contains', $content) +// ->assertCanSeeTableRecords($post->get()) +// ->callTableAction(DeleteAction::class, $post->first()); + +// assertSoftDeleted($post->first()); +// }); diff --git a/tests/src/Tables/Fixtures/PostsQueryBuilderTable.php b/tests/src/Tables/Fixtures/PostsQueryBuilderTable.php new file mode 100644 index 00000000000..5a1b9a780f0 --- /dev/null +++ b/tests/src/Tables/Fixtures/PostsQueryBuilderTable.php @@ -0,0 +1,53 @@ +query(Post::query()) + ->columns([ + Tables\Columns\TextColumn::make('title') + ->sortable() + ->searchable(), + Tables\Columns\TextColumn::make('author.name') + ->sortable() + ->searchable(), + ]) + ->filters([ + QueryBuilder::make() + ->constraints([ + TextConstraint::make('content') + ->nullable(), + ]), + ]) + ->actions([ + Tables\Actions\ViewAction::make(), + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + ]) + ->bulkActions([ + Tables\Actions\DeleteBulkAction::make(), + ]); + } + + public function render(): View + { + return view('tables.fixtures.table'); + } +} From 6f775613a1aafc6c64494795d72877ad0a096492 Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 03:19:57 +0900 Subject: [PATCH 02/12] wip --- packages/tables/.stubs.php | 2 +- .../tables/src/Testing/TestsQueryBuilders.php | 42 ++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/packages/tables/.stubs.php b/packages/tables/.stubs.php index 75936ad031c..6922ef65523 100644 --- a/packages/tables/.stubs.php +++ b/packages/tables/.stubs.php @@ -177,7 +177,7 @@ public function assertCanSeeTableRecords(array | Collection $records, bool $inOr public function assertCanNotSeeTableRecords(array | Collection $records): static {} - public function queryBuilderTable(string $column, string $operator, $data = null): static {} + public function queryBuilderTable(string $filter, string $operator, $data = null): static {} public function assertCountTableRecords(int $count): static {} diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php index 9c6489e8ed5..fc63dff877e 100644 --- a/packages/tables/src/Testing/TestsQueryBuilders.php +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -5,6 +5,9 @@ use Closure; use Filament\Tables\Filters\QueryBuilder\Concerns\HasConstraints; use Filament\Tables\Filters\QueryBuilder\Constraints\Constraint; +use Filament\Tables\Filters\QueryBuilder\Constraints\DateConstraint; +use Filament\Tables\Filters\QueryBuilder\Constraints\NumberConstraint; +use Filament\Tables\Filters\QueryBuilder\Constraints\SelectConstraint; use Filament\Tables\Filters\QueryBuilder\Constraints\TextConstraint; use Illuminate\Testing\Assert; use Livewire\Features\SupportTesting\Testable; @@ -18,24 +21,35 @@ class TestsQueryBuilders { public function queryBuilderTable(): Closure { - return function (string $column, string $operator, $data = null): static { + return function (string $filter, string $operator, $data = null): static { /** @phpstan-ignore-next-line */ - $this->assertTableConstraintExists($column); + $this->assertTableConstraintExists($filter); - $constraint = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($column); + $constraint = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($filter); + $queryBuilder = [ + 'type' => $filter, + 'data' => [ + 'operator' => $operator, + 'settings' => [], + ] + ]; if ($constraint instanceof TextConstraint) { - $queryBuilder = [ - 'type' => $column, - 'data' => [ - 'operator' => $operator, - 'settings' => [], - ] - ]; - if ($data) { $queryBuilder['data']['settings'] = ['text' => $data]; } + } elseif ($constraint instanceof NumberConstraint) { + if ($data) { + $queryBuilder['data']['settings'] = ['number' => $data]; + } + } elseif ($constraint instanceof DateConstraint) { + if ($data) { + $queryBuilder['data']['settings'] = ['date' => $data]; + } + } elseif ($constraint instanceof SelectConstraint) { + if ($data) { + $queryBuilder['data']['settings'] = ['values' => $data]; + } } $this->set("tableFilters.queryBuilder.rules.{$constraint->getName()}", $queryBuilder); @@ -46,15 +60,15 @@ public function queryBuilderTable(): Closure public function assertTableConstraintExists(): Closure { - return function (string $column): static { - $filter = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($column); + return function (string $name): static { + $filter = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($name); $livewireClass = $this->instance()::class; Assert::assertInstanceOf( Constraint::class, $filter, - message: "Failed asserting that a table filter with name [{$column}] exists on the [{$livewireClass}] component.", + message: "Failed asserting that a query builder with name [{$name}] exists on the [{$livewireClass}] component.", ); return $this; From 90450c7913dd6b2b8450a5b6f54f519e812f899c Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 03:35:52 +0900 Subject: [PATCH 03/12] feat: simplify test cases --- tests/src/Tables/Filters/QueryBuilderTest.php | 84 ++----------------- 1 file changed, 5 insertions(+), 79 deletions(-) diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index 48b0458a02f..1e74a07a14c 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -1,18 +1,17 @@ create(); $content = $posts->random()->content; - $filter = substr($content, 2, 7); + $start = fake()->numberBetween(0, strlen($content)); + $filter = substr($content, $start, fake()->numberBetween($start, strlen($content))); livewire(PostsQueryBuilderTable::class) ->assertCanSeeTableRecords($posts) @@ -21,22 +20,10 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter . '%')->get()); }); -it('can filter text constraint for `not contains`', function () { - $posts = Post::factory(10)->create(); - $content = $posts->random()->content; - $filter = substr($content, 2, 7); - - livewire(PostsQueryBuilderTable::class) - ->assertCanSeeTableRecords($posts) - ->queryBuilderTable('content', 'contains.inverse', $filter) - ->assertCanSeeTableRecords(Post::where('content', 'not like', '%' . $filter . '%')->get()) - ->assertCanNotSeeTableRecords(Post::where('content', 'like', '%' . $filter . '%')->get()); -}); - it('can filter text constraint for `startsWith`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; - $filter = substr($content, 0, 5); + $filter = substr($content, 0, fake()->numberBetween(1, strlen($content))); livewire(PostsQueryBuilderTable::class) ->assertCanSeeTableRecords($posts) @@ -45,22 +32,10 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', $filter . '%')->get()); }); -it('can filter text constraint for `not startsWith`', function () { - $posts = Post::factory(10)->create(); - $content = $posts->random()->content; - $filter = substr($content, 0, 5); - - livewire(PostsQueryBuilderTable::class) - ->assertCanSeeTableRecords($posts) - ->queryBuilderTable('content', 'startsWith.inverse', $filter) - ->assertCanSeeTableRecords(Post::where('content', 'not like', $filter . '%')->get()) - ->assertCanNotSeeTableRecords(Post::where('content', 'like', $filter . '%')->get()); -}); - it('can filter text constraint for `endsWith`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; - $filter = substr($content, -5); + $filter = substr($content, -(fake()->numberBetween(1, strlen($content)))); livewire(PostsQueryBuilderTable::class) ->assertCanSeeTableRecords($posts) @@ -69,18 +44,6 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter)->get()); }); -it('can filter text constraint for `not endsWith`', function () { - $posts = Post::factory(10)->create(); - $content = $posts->random()->content; - $filter = substr($content, -5); - - livewire(PostsQueryBuilderTable::class) - ->assertCanSeeTableRecords($posts) - ->queryBuilderTable('content', 'endsWith.inverse', $filter) - ->assertCanSeeTableRecords(Post::where('content', 'not like', '%' . $filter)->get()) - ->assertCanNotSeeTableRecords(Post::where('content', 'like', '%' . $filter)->get()); -}); - it('can filter text constraint for `equals`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; @@ -92,19 +55,8 @@ ->assertCanNotSeeTableRecords(Post::where('content', '<>', $content)->get()); }); -it('can filter text constraint for `not equals`', function () { - $posts = Post::factory(10)->create(); - $content = $posts->random()->content; - - livewire(PostsQueryBuilderTable::class) - ->assertCanSeeTableRecords($posts) - ->queryBuilderTable('content', 'equals.inverse', $content) - ->assertCanSeeTableRecords(Post::where('content', '<>', $content)->get()) - ->assertCanNotSeeTableRecords(Post::where('content', $content)->get()); -}); - it('can filter text constraint for `isFilled`', function () { - Post::factory(8)->create(); + Post::factory()->create(); Post::factory()->create(['content' => null]); Post::factory()->create(['content' => '']); @@ -114,29 +66,3 @@ ->assertCanSeeTableRecords(Post::where('content', '<>', null)->where('content', '<>', '')->get()) ->assertCanNotSeeTableRecords(Post::where('content', null)->orWhere('content', '')->get()); }); - -it('can filter text constraint for `not isFilled`', function () { - Post::factory(8)->create(); - Post::factory()->create(['content' => null]); - Post::factory()->create(['content' => '']); - - livewire(PostsQueryBuilderTable::class) - ->assertCanSeeTableRecords(Post::all()) - ->queryBuilderTable('content', 'isFilled.inverse') - ->assertCanSeeTableRecords(Post::where('content', null)->orWhere('content', '')->get()) - ->assertCanNotSeeTableRecords(Post::where('content', '<>', null)->where('content', '<>', '')->get()); -}); - -// it('can filter records by text constraint in the query builder with modal action', function () { -// $posts = Post::factory()->count(10)->create(); -// $content = $posts->first()->content; -// $post = Post::where('content', $content); - -// livewire(PostsQueryBuilderTable::class) -// ->assertCanSeeTableRecords($posts) -// ->queryBuilderTable('content', 'contains', $content) -// ->assertCanSeeTableRecords($post->get()) -// ->callTableAction(DeleteAction::class, $post->first()); - -// assertSoftDeleted($post->first()); -// }); From a1263540b33a41558c19cfb888aae38a13e177c4 Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 03:43:44 +0900 Subject: [PATCH 04/12] chore: change comment --- tests/src/Tables/Filters/QueryBuilderTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index 1e74a07a14c..eed9f9f5f0f 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -7,7 +7,7 @@ uses(TestCase::class); -it('can filter text constraint for `contains`', function () { +it('can filter text constraint by `contains`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; $start = fake()->numberBetween(0, strlen($content)); @@ -20,7 +20,7 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter . '%')->get()); }); -it('can filter text constraint for `startsWith`', function () { +it('can filter text constraint by `startsWith`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; $filter = substr($content, 0, fake()->numberBetween(1, strlen($content))); @@ -32,7 +32,7 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', $filter . '%')->get()); }); -it('can filter text constraint for `endsWith`', function () { +it('can filter text constraint by `endsWith`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; $filter = substr($content, -(fake()->numberBetween(1, strlen($content)))); @@ -44,7 +44,7 @@ ->assertCanNotSeeTableRecords(Post::where('content', 'not like', '%' . $filter)->get()); }); -it('can filter text constraint for `equals`', function () { +it('can filter text constraint by `equals`', function () { $posts = Post::factory(10)->create(); $content = $posts->random()->content; @@ -55,7 +55,7 @@ ->assertCanNotSeeTableRecords(Post::where('content', '<>', $content)->get()); }); -it('can filter text constraint for `isFilled`', function () { +it('can filter text constraint by `isFilled`', function () { Post::factory()->create(); Post::factory()->create(['content' => null]); Post::factory()->create(['content' => '']); From a6f123838203469c594ee07b78c4a7121ec4d189 Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 03:46:15 +0900 Subject: [PATCH 05/12] chore: fix code style --- packages/tables/src/Testing/TestsQueryBuilders.php | 2 +- tests/src/Tables/Filters/QueryBuilderTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php index fc63dff877e..e25ceed9c1c 100644 --- a/packages/tables/src/Testing/TestsQueryBuilders.php +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -32,7 +32,7 @@ public function queryBuilderTable(): Closure 'data' => [ 'operator' => $operator, 'settings' => [], - ] + ], ]; if ($constraint instanceof TextConstraint) { if ($data) { diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index eed9f9f5f0f..1fbf8fbeea0 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -3,6 +3,7 @@ use Filament\Tests\Models\Post; use Filament\Tests\Tables\Fixtures\PostsQueryBuilderTable; use Filament\Tests\Tables\TestCase; + use function Filament\Tests\livewire; uses(TestCase::class); From d4bc4d222d83ba0070dc8821de039b277b9569b3 Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 04:01:22 +0900 Subject: [PATCH 06/12] chore: minor fix --- packages/tables/src/Testing/TestsQueryBuilders.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php index e25ceed9c1c..3eedfc147e1 100644 --- a/packages/tables/src/Testing/TestsQueryBuilders.php +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -3,7 +3,7 @@ namespace Filament\Tables\Testing; use Closure; -use Filament\Tables\Filters\QueryBuilder\Concerns\HasConstraints; +use Filament\Tables\Contracts\HasTable; use Filament\Tables\Filters\QueryBuilder\Constraints\Constraint; use Filament\Tables\Filters\QueryBuilder\Constraints\DateConstraint; use Filament\Tables\Filters\QueryBuilder\Constraints\NumberConstraint; @@ -13,7 +13,7 @@ use Livewire\Features\SupportTesting\Testable; /** - * @method HasConstraints instance() + * @method HasTable instance() * * @mixin Testable */ From 6a4eeeed819d1490a30d67ee82b4f492d5c755fc Mon Sep 17 00:00:00 2001 From: bzy107 Date: Wed, 26 Feb 2025 04:10:27 +0900 Subject: [PATCH 07/12] fix: ignore phpstan --- packages/tables/src/Testing/TestsQueryBuilders.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php index 3eedfc147e1..aff9fc044fd 100644 --- a/packages/tables/src/Testing/TestsQueryBuilders.php +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -25,6 +25,7 @@ public function queryBuilderTable(): Closure /** @phpstan-ignore-next-line */ $this->assertTableConstraintExists($filter); + /** @phpstan-ignore-next-line */ $constraint = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($filter); $queryBuilder = [ @@ -61,6 +62,7 @@ public function queryBuilderTable(): Closure public function assertTableConstraintExists(): Closure { return function (string $name): static { + /** @phpstan-ignore-next-line */ $filter = $this->instance()->getTable()->getFilter('queryBuilder')->getConstraint($name); $livewireClass = $this->instance()::class; From 918d46856de0cb2eb624884a459bf108a2b94c5c Mon Sep 17 00:00:00 2001 From: Fabien Karsegard Date: Mon, 17 Mar 2025 18:29:09 +0100 Subject: [PATCH 08/12] fix: infinite loop when caching form with mounted table action with query builders --- packages/forms/src/Concerns/InteractsWithForms.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/forms/src/Concerns/InteractsWithForms.php b/packages/forms/src/Concerns/InteractsWithForms.php index a88b84b3fcf..c5f58bc6e02 100644 --- a/packages/forms/src/Concerns/InteractsWithForms.php +++ b/packages/forms/src/Concerns/InteractsWithForms.php @@ -326,6 +326,9 @@ protected function cacheForm(string $name, Form | Closure | null $form): ?Form */ protected function cacheForms(): array { + if($this->isCachingForms()){ + return []; + } $this->isCachingForms = true; $this->cachedForms = collect($this->getForms()) From 6b296d4a1bd6df3fd8b9b3285d8a7b9ddd31b194 Mon Sep 17 00:00:00 2001 From: Fabien Karsegard Date: Mon, 17 Mar 2025 18:29:36 +0100 Subject: [PATCH 09/12] fix: Error in queryBuilder test --- packages/tables/src/Testing/TestsQueryBuilders.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tables/src/Testing/TestsQueryBuilders.php b/packages/tables/src/Testing/TestsQueryBuilders.php index aff9fc044fd..38ab860b3b6 100644 --- a/packages/tables/src/Testing/TestsQueryBuilders.php +++ b/packages/tables/src/Testing/TestsQueryBuilders.php @@ -70,7 +70,7 @@ public function assertTableConstraintExists(): Closure Assert::assertInstanceOf( Constraint::class, $filter, - message: "Failed asserting that a query builder with name [{$name}] exists on the [{$livewireClass}] component.", + "Failed asserting that a query builder with name [{$name}] exists on the [{$livewireClass}] component.", ); return $this; From 246bfdfdd392fc0bd4cad93c57257f0221b265b1 Mon Sep 17 00:00:00 2001 From: Fabien Karsegard Date: Mon, 17 Mar 2025 18:45:10 +0100 Subject: [PATCH 10/12] fix: adapted test for querybuilder action infinite loop --- tests/src/Tables/Filters/QueryBuilderTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index 1fbf8fbeea0..804531c2708 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -4,7 +4,9 @@ use Filament\Tests\Tables\Fixtures\PostsQueryBuilderTable; use Filament\Tests\Tables\TestCase; +use Filament\Tables\Actions\DeleteAction; use function Filament\Tests\livewire; +use function Pest\Laravel\assertSoftDeleted; uses(TestCase::class); @@ -67,3 +69,16 @@ ->assertCanSeeTableRecords(Post::where('content', '<>', null)->where('content', '<>', '')->get()) ->assertCanNotSeeTableRecords(Post::where('content', null)->orWhere('content', '')->get()); }); + +it('can modal actions during text constraint', function () { + $posts = Post::factory()->count(10)->create(); + $content = $posts->first()->content; + $post = Post::where('content', $content); + + livewire(PostsQueryBuilderTable::class) + ->assertCanSeeTableRecords($posts) + ->queryBuilderTable('content', 'contains', $content) + ->assertCanSeeTableRecords($post->get()) + ->callTableAction(DeleteAction::class, $post->first()) + ->assertCanNotSeeTableRecords([$posts->first()]); +}); \ No newline at end of file From 9825ffdd3f6ec38a4db7e8e1de806b72cf562823 Mon Sep 17 00:00:00 2001 From: Fabien Karsegard Date: Mon, 17 Mar 2025 18:48:56 +0100 Subject: [PATCH 11/12] code style --- packages/forms/src/Concerns/InteractsWithForms.php | 2 +- tests/src/Tables/Filters/QueryBuilderTest.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/forms/src/Concerns/InteractsWithForms.php b/packages/forms/src/Concerns/InteractsWithForms.php index c5f58bc6e02..4240e269de3 100644 --- a/packages/forms/src/Concerns/InteractsWithForms.php +++ b/packages/forms/src/Concerns/InteractsWithForms.php @@ -326,7 +326,7 @@ protected function cacheForm(string $name, Form | Closure | null $form): ?Form */ protected function cacheForms(): array { - if($this->isCachingForms()){ + if ($this->isCachingForms()) { return []; } $this->isCachingForms = true; diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index 804531c2708..1571a8a3ec2 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -1,12 +1,11 @@ assertCanSeeTableRecords($post->get()) ->callTableAction(DeleteAction::class, $post->first()) ->assertCanNotSeeTableRecords([$posts->first()]); -}); \ No newline at end of file +}); From 536874a9892ab61fd6af87cff86dc1a9559bc234 Mon Sep 17 00:00:00 2001 From: Fabien Karsegard Date: Mon, 17 Mar 2025 19:09:27 +0100 Subject: [PATCH 12/12] Update QueryBuilderTest.php --- tests/src/Tables/Filters/QueryBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Tables/Filters/QueryBuilderTest.php b/tests/src/Tables/Filters/QueryBuilderTest.php index 1571a8a3ec2..ce27600cbca 100644 --- a/tests/src/Tables/Filters/QueryBuilderTest.php +++ b/tests/src/Tables/Filters/QueryBuilderTest.php @@ -79,5 +79,5 @@ ->queryBuilderTable('content', 'contains', $content) ->assertCanSeeTableRecords($post->get()) ->callTableAction(DeleteAction::class, $post->first()) - ->assertCanNotSeeTableRecords([$posts->first()]); + ->assertCanNotSeeTableRecords($post->get()); });