actingAsSysUser(); $ids = ProductModel::factory()->count(3)->create()->pluck('id')->all(); $this->postJson('/client/special/batch', ['product_ids' => $ids]) ->assertOk() ->assertJsonPath('success', true) ->assertJsonPath('data.added', 3) ->assertJsonPath('data.skipped', 0); foreach ($ids as $id) { $this->assertDatabaseHas('mini_home_special', [ 'product_id' => $id, 'status' => HomeSpecialModel::STATUS_NORMAL, ]); } } /** 重复添加:已在推荐中的商品自动跳过,不产生重复行 */ public function test_batch_add_skips_existing_products(): void { $this->actingAsSysUser(); [$a, $b] = ProductModel::factory()->count(2)->create()->all(); HomeSpecialModel::create(['product_id' => $a->id, 'sort' => 0, 'status' => 1]); $this->postJson('/client/special/batch', ['product_ids' => [$a->id, $b->id]]) ->assertOk() ->assertJsonPath('success', true) ->assertJsonPath('data.added', 1) ->assertJsonPath('data.skipped', 1); $this->assertSame(1, HomeSpecialModel::where('product_id', $a->id)->count()); $this->assertSame(2, HomeSpecialModel::count()); } /** product_ids 为空数组 → 校验失败,不添加任何推荐 */ public function test_batch_add_requires_non_empty_product_ids(): void { $this->actingAsSysUser(); ProductModel::factory()->create(); $this->postJson('/client/special/batch', ['product_ids' => []]) ->assertOk() ->assertJsonPath('success', false) ->assertJsonPath('msg', '请选择要添加的商品'); $this->assertSame(0, HomeSpecialModel::count()); } /** 无 client.special.create 权限点 → 拦截 */ public function test_batch_add_forbidden_without_permission(): void { // 先建占位用户:每个测试方法内首个系统用户自增 id=1,超管旁路会绕过 abilities 校验 $this->actingAsSysUser(); $this->actingAsSysUser(['client.special.query']); $product = ProductModel::factory()->create(); $this->postJson('/client/special/batch', ['product_ids' => [$product->id]]) ->assertOk() ->assertJsonPath('success', false) ->assertJsonPath('msg', 'No Permission'); $this->assertSame(0, HomeSpecialModel::count()); } /** 列表 keyword 按商品名模糊过滤,行内附带商品信息 */ public function test_query_filters_by_product_name_keyword(): void { $this->actingAsSysUser(); $cabbage = ProductModel::factory()->create(['name' => '有机大白菜']); $apple = ProductModel::factory()->create(['name' => '红富士苹果']); HomeSpecialModel::create(['product_id' => $cabbage->id, 'sort' => 0, 'status' => 1]); HomeSpecialModel::create(['product_id' => $apple->id, 'sort' => 0, 'status' => 1]); $data = $this->getJson('/client/special?keyword=' . urlencode('白菜')) ->assertOk() ->json('data'); $this->assertSame(1, $data['total']); $this->assertSame('有机大白菜', $data['data'][0]['product']['name']); } /** 编辑:仅排序与状态可改 */ public function test_update_changes_sort_and_status(): void { $this->actingAsSysUser(); $special = HomeSpecialModel::create([ 'product_id' => ProductModel::factory()->create()->id, 'sort' => 0, 'status' => 1, ]); $this->putJson("/client/special/{$special->id}", ['sort' => 5, 'status' => 0]) ->assertOk() ->assertJsonPath('success', true); $this->assertDatabaseHas('mini_home_special', [ 'id' => $special->id, 'sort' => 5, 'status' => 0, ]); } /** 单个删除 + 批量删除:选中的删除,未选中的保留 */ public function test_delete_and_batch_delete(): void { $this->actingAsSysUser(); $products = ProductModel::factory()->count(3)->create(); $specials = $products->map(static fn ($p) => HomeSpecialModel::create([ 'product_id' => $p->id, 'sort' => 0, 'status' => 1, ])); $this->deleteJson("/client/special/{$specials[0]->id}") ->assertOk() ->assertJsonPath('success', true); $this->assertDatabaseMissing('mini_home_special', ['id' => $specials[0]->id]); $this->deleteJson('/client/special/batch', ['ids' => [$specials[1]->id]]) ->assertOk() ->assertJsonPath('success', true); $this->assertDatabaseMissing('mini_home_special', ['id' => $specials[1]->id]); $this->assertDatabaseHas('mini_home_special', ['id' => $specials[2]->id]); } /** 批量删除 ids 为空 → 校验失败 */ public function test_batch_delete_requires_non_empty_ids(): void { $this->actingAsSysUser(); $special = HomeSpecialModel::create([ 'product_id' => ProductModel::factory()->create()->id, 'sort' => 0, 'status' => 1, ]); $this->deleteJson('/client/special/batch', ['ids' => []]) ->assertOk() ->assertJsonPath('success', false) ->assertJsonPath('msg', '请选择要删除的推荐'); $this->assertDatabaseHas('mini_home_special', ['id' => $special->id]); } }