Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Modules\Core\Enums\Permission;
use Modules\Products\Enums\ProductType;
use Modules\Products\Models\Product;
use Modules\Products\Models\ProductCategory;
use Modules\Products\Models\ProductUnit;
use Modules\Products\Services\ProductService;

class ProductsTable
Expand Down Expand Up @@ -59,7 +62,20 @@ public static function configure(Table $table): Table
->toggleable()
->hiddenFrom('md'),
])
->filters([])
->filters([
SelectFilter::make('category_id')
->label(trans('ip.category'))
->options(fn (): array => ProductCategory::query()
->orderBy('category_name')
->pluck('category_name', 'id')
->toArray()),
SelectFilter::make('unit_id')
->label(trans('ip.unit'))
->options(fn (): array => ProductUnit::query()
->orderBy('unit_name')
->pluck('unit_name', 'id')
->toArray()),
])
->recordActions([
ActionGroup::make([
EditAction::make('edit')
Expand Down
109 changes: 109 additions & 0 deletions Modules/Products/Tests/Feature/ProductCategoryFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace Modules\Products\Tests\Feature;

use Illuminate\Support\Str;
use Livewire\Livewire;
use Modules\Core\Tests\AbstractCompanyPanelTestCase;
use Modules\Products\Filament\Company\Resources\Products\Pages\ListProducts;
use Modules\Products\Filament\Company\Resources\Products\ProductResource;
use Modules\Products\Models\Product;
use Modules\Products\Models\ProductCategory;
use Modules\Products\Models\ProductUnit;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\Test;

#[CoversClass(ProductResource::class)]
class ProductCategoryFilterTest extends AbstractCompanyPanelTestCase
{
#[Test]
#[Group('crud')]
public function it_filters_products_by_category(): void
{
/* Arrange */
$hardware = ProductCategory::factory()->for($this->company)->create([
'category_name' => 'Hardware',
]);
$software = ProductCategory::factory()->for($this->company)->create([
'category_name' => 'Software',
]);

$hardwareProduct = Product::factory()->for($this->company)->create([
'category_id' => $hardware->id,
'product_name' => 'Hardware Product',
]);
$softwareProduct = Product::factory()->for($this->company)->create([
'category_id' => $software->id,
'product_name' => 'Software Product',
]);

/* Act + Assert */
Livewire::actingAs($this->user)
->test(ListProducts::class, ['tenant' => Str::lower($this->company->search_code)])
->assertSuccessful()
->assertCanSeeTableRecords([$hardwareProduct, $softwareProduct])
->filterTable('category_id', $hardware->id)
->assertCanSeeTableRecords([$hardwareProduct])
->assertCanNotSeeTableRecords([$softwareProduct]);
}

#[Test]
#[Group('crud')]
public function it_filters_products_by_unit(): void
{
/* Arrange */
$piece = ProductUnit::factory()->for($this->company)->create([
'unit_name' => 'Piece',
]);
$hour = ProductUnit::factory()->for($this->company)->create([
'unit_name' => 'Hour',
]);

$pieceProduct = Product::factory()->for($this->company)->create([
'unit_id' => $piece->id,
'product_name' => 'Piece Product',
]);
$hourProduct = Product::factory()->for($this->company)->create([
'unit_id' => $hour->id,
'product_name' => 'Hour Product',
]);

/* Act + Assert */
Livewire::actingAs($this->user)
->test(ListProducts::class, ['tenant' => Str::lower($this->company->search_code)])
->assertSuccessful()
->assertCanSeeTableRecords([$pieceProduct, $hourProduct])
->filterTable('unit_id', $piece->id)
->assertCanSeeTableRecords([$pieceProduct])
->assertCanNotSeeTableRecords([$hourProduct]);
}

#[Test]
#[Group('multi-tenancy')]
public function it_only_offers_categories_of_the_current_tenant_as_filter_options(): void
{
/* Arrange */
$ownCategory = ProductCategory::factory()->for($this->company)->create([
'category_name' => 'Own Category',
]);
$companyB = \Modules\Core\Models\Company::factory()->create();
$foreignCategory = ProductCategory::factory()->for($companyB)->create([
'category_name' => 'Foreign Category',
]);
Comment on lines +87 to +93

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Unused variables $ownCategory/$foreignCategory flagged by static analysis; use them instead of hard-coded strings.

Static analysis reports both variables as unused since the assertions reference literal strings rather than the created models' attributes, which also weakens the test's coupling to the actual seeded data.

🧹 Suggested fix
-        $this->assertContains('Own Category', $options);
-        $this->assertNotContains('Foreign Category', $options);
+        $this->assertContains($ownCategory->category_name, $options);
+        $this->assertNotContains($foreignCategory->category_name, $options);

Also applies to: 106-107

🧰 Tools
🪛 PHPMD (2.15.0)

[warning] 87-87: Avoid unused local variables such as '$ownCategory'. (undefined)

(UnusedLocalVariable)


[warning] 91-91: Avoid unused local variables such as '$foreignCategory'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Modules/Products/Tests/Feature/ProductCategoryFilterTest.php` around lines 87
- 93, The test setup in ProductCategoryFilterTest creates `$ownCategory` and
`$foreignCategory` but the assertions still use hard-coded category names, so
the variables are unused. Update the relevant assertions in the test methods
that use these fixtures to reference the models’ `category_name` values instead
of literals, using the existing `ProductCategory` variables so the test stays
aligned with the seeded data and static analysis no longer flags them.

Source: Linters/SAST tools


/* Act */
$component = Livewire::actingAs($this->user)
->test(ListProducts::class, ['tenant' => Str::lower($this->company->search_code)])
->assertSuccessful();

/* Assert — filter options are tenant-scoped by the BelongsToCompany global scope */
$options = $component->instance()
->getTable()
->getFilter('category_id')
->getOptions();

$this->assertContains('Own Category', $options);
$this->assertNotContains('Foreign Category', $options);
}
}
Loading