Files
xin-procurement/tests/Feature/ExportTest.php
T
2026-07-23 20:41:25 +08:00

122 lines
4.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Tests\Feature;
use App\Exports\PurchaseOrderExport;
use App\Models\CustomerLevelModel;
use App\Models\ProductCategoryModel;
use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use App\Models\PurchaseOrderModel;
use App\Models\StoreModel;
use App\Models\UserModel;
use Maatwebsite\Excel\Facades\Excel;
/**
* 采购单导出:xlsx Content-Type / 蔬果分类过滤 / PDF / format 非法拒绝 / 权限拦截 /
* 中文文件名 RFC 5987 编码
*/
class ExportTest extends ProcurementTestCase
{
/**
* 构造含蔬果 + 肉禽两类商品的采购单(下单 → 汇总生成)
*/
private function buildPurchaseWithItems(): PurchaseOrderModel
{
$vegRoot = ProductCategoryModel::create(['name' => '蔬菜', 'parent_id' => 0, 'sort' => 0, 'status' => 1]);
$meatRoot = ProductCategoryModel::create(['name' => '肉禽蛋', 'parent_id' => 0, 'sort' => 1, 'status' => 1]);
$level = CustomerLevelModel::factory()->create();
$store = StoreModel::factory()->create(['level_id' => $level->id]);
$veg = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON, 'category_id' => $vegRoot->id]);
$meat = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON, 'category_id' => $meatRoot->id]);
ProductPriceModel::factory()->create(['product_id' => $veg->id, 'level_id' => $level->id, 'price' => '5.00']);
ProductPriceModel::factory()->create(['product_id' => $meat->id, 'level_id' => $level->id, 'price' => '20.00']);
$this->actingAsMiniUser(UserModel::factory()->forStore($store->id)->create());
$this->postJson('/mini/order', ['items' => [
['product_id' => $veg->id, 'quantity' => 2],
['product_id' => $meat->id, 'quantity' => 1],
]])->assertJsonPath('success', true);
$this->actingAsSysUser();
$this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()])
->assertJsonPath('success', true);
return PurchaseOrderModel::first();
}
/** xlsx 导出:正确 Content-Type + 中文文件名 RFC 5987 编码 */
public function test_export_xlsx_with_encoded_chinese_filename(): void
{
$purchase = $this->buildPurchaseWithItems();
$this->actingAsSysUser();
$response = $this->get("/purchase/order/{$purchase->id}/export?type=all&format=xlsx");
$response->assertOk();
$this->assertStringContainsString(
'spreadsheetml',
(string) $response->headers->get('Content-Type'),
'xlsx 应返回电子表格 Content-Type'
);
$disposition = (string) $response->headers->get('Content-Disposition');
// Symfony 输出小写 utf-8''RFC 5987),大小写不敏感断言
$this->assertMatchesRegularExpression("/filename\*=utf-8''/i", $disposition, '中文文件名应走 RFC 5987 编码');
$this->assertStringContainsString(rawurlencode('采购单'), $disposition);
}
/** 蔬果分类过滤:type=category 仅导出蔬菜/水果顶级分类商品 */
public function test_export_category_filters_to_vegetables(): void
{
$purchase = $this->buildPurchaseWithItems();
$this->actingAsSysUser();
Excel::fake();
$this->get("/purchase/order/{$purchase->id}/export?type=category&format=xlsx")->assertOk();
Excel::assertDownloaded(
$purchase->purchase_no . '_采购单.xlsx',
static function (PurchaseOrderExport $export): bool {
$items = $export->collection();
// 仅蔬菜商品一行,肉禽被过滤
return $items->count() === 1;
}
);
}
/** PDF 导出:application/pdf */
public function test_export_pdf(): void
{
$purchase = $this->buildPurchaseWithItems();
$this->actingAsSysUser();
$response = $this->get("/purchase/order/{$purchase->id}/export?format=pdf");
$response->assertOk();
$this->assertStringContainsString('application/pdf', (string) $response->headers->get('Content-Type'));
$this->assertStringStartsWith('%PDF', (string) $response->getContent());
}
/** format 参数非法 → 拒绝 */
public function test_export_invalid_format_rejected(): void
{
$purchase = $this->buildPurchaseWithItems();
$this->actingAsSysUser();
$this->get("/purchase/order/{$purchase->id}/export?format=doc")
->assertJsonPath('success', false);
}
/** 无 purchase.order.export 权限点 → 拦截 */
public function test_export_requires_export_permission(): void
{
$purchase = $this->buildPurchaseWithItems();
// 仅持有查询权限的用户
$this->actingAsSysUser(['purchase.order.query']);
$response = $this->get("/purchase/order/{$purchase->id}/export?format=xlsx");
$this->assertFalse($response->json('success'), '缺少权限点应被拦截');
}
}