Files
xin-procurement/tests/Feature/ProductCategoryTest.php
T
2026-08-14 16:31:18 +08:00

183 lines
6.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\ProductCategoryModel;
use App\Models\UserModel;
/**
* 商品分类两级限制 + 商品只能挂末级分类:
* 创建/编辑分类的父级必须为顶级、含子分类的分类不可移动为子级、商品分类必须为末级
*/
class ProductCategoryTest extends ProcurementTestCase
{
/** 造一个顶级分类 */
private function makeTopCategory(string $name = '蔬菜'): ProductCategoryModel
{
return ProductCategoryModel::create([
'parent_id' => 0,
'name' => $name,
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
}
/** 顶级分类下可创建子分类(二级) */
public function test_create_child_category_under_top_level(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory();
$this->postJson('/product/category', [
'parent_id' => $top->id,
'name' => '叶菜类',
])->assertOk()->assertJsonPath('success', true);
$this->assertDatabaseHas('product_category', ['name' => '叶菜类', 'parent_id' => $top->id]);
}
/** 二级分类不可作为父级(最多二级) */
public function test_create_category_under_second_level_rejected(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory();
$child = ProductCategoryModel::create([
'parent_id' => $top->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$this->postJson('/product/category', [
'parent_id' => $child->id,
'name' => '菠菜',
])->assertOk()
->assertJsonPath('success', false)
->assertJsonPath('msg', '最多支持二级分类,不能选择子分类作为上级');
}
/** 编辑:二级分类可平级移动到另一个顶级分类下 */
public function test_update_second_level_move_to_another_top(): void
{
$this->actingAsSysUser();
$topA = $this->makeTopCategory('蔬菜');
$topB = $this->makeTopCategory('水果');
$child = ProductCategoryModel::create([
'parent_id' => $topA->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$this->putJson('/product/category/' . $child->id, [
'parent_id' => $topB->id,
'name' => '叶菜类',
])->assertOk()->assertJsonPath('success', true);
$this->assertSame($topB->id, (int) $child->fresh()->parent_id);
}
/** 编辑:含子分类的分类不能调整为子分类(否则子分类变三级) */
public function test_update_parent_with_children_cannot_move_under_category(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory('蔬菜');
$other = $this->makeTopCategory('水果');
ProductCategoryModel::create([
'parent_id' => $top->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$this->putJson('/product/category/' . $top->id, [
'parent_id' => $other->id,
'name' => '蔬菜',
])->assertOk()
->assertJsonPath('success', false)
->assertJsonPath('msg', '该分类下存在子分类,不能调整为子分类');
}
/** 编辑:父级不存在时提示 */
public function test_update_with_missing_parent_rejected(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory();
$this->putJson('/product/category/' . $top->id, [
'parent_id' => 99999,
'name' => '蔬菜',
])->assertOk()
->assertJsonPath('success', false)
->assertJsonPath('msg', '父级分类不存在');
}
/** 商品只能挂在末级分类:选择有子分类的分类创建商品 → 验证失败 */
public function test_create_product_with_parent_category_rejected(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory('蔬菜');
ProductCategoryModel::create([
'parent_id' => $top->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$this->postJson('/product/goods', [
'category_id' => $top->id,
'name' => '大白菜',
])->assertOk()
->assertJsonPath('success', false)
->assertJsonPath('msg', '该分类下存在子分类,请选择末级分类');
}
/** 商品挂在末级分类(无子分类)可正常创建 */
public function test_create_product_with_leaf_category_ok(): void
{
$this->actingAsSysUser();
$top = $this->makeTopCategory('蔬菜');
$leaf = ProductCategoryModel::create([
'parent_id' => $top->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$this->postJson('/product/goods', [
'category_id' => $leaf->id,
'name' => '大白菜',
'content' => '图文详情',
])->assertOk()->assertJsonPath('success', true);
}
/** 小程序分类树:返回全部启用分类(含无商品的分类),停用分类不返回 */
public function test_mini_categories_returns_all_enabled_categories(): void
{
$top = $this->makeTopCategory('蔬菜');
$empty = $this->makeTopCategory('水产'); // 无任何商品
ProductCategoryModel::create([
'parent_id' => $top->id,
'name' => '叶菜类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_NORMAL,
]);
$disabled = ProductCategoryModel::create([
'parent_id' => 0,
'name' => '停用分类',
'sort' => 1,
'status' => ProductCategoryModel::STATUS_DISABLED,
]);
$this->actingAsMiniUser(UserModel::factory()->create());
$response = $this->getJson('/mini/product/categories');
$response->assertOk()->assertJsonPath('success', true);
$ids = collect($response->json('data'))->pluck('id');
$this->assertContains($top->id, $ids);
$this->assertContains($empty->id, $ids, '无商品的分类也应返回');
$this->assertNotContains($disabled->id, $ids, '停用分类不应返回');
}
}