CaiWuXiTong/tests/Feature/Business/CourierFreightReconciliationPageTest.php

109 lines
6.0 KiB
PHP

<?php
namespace Tests\Feature\Business;
use App\Models\Auth\Permission;
use Illuminate\Testing\TestResponse;
use Modules\EcommerceFinance\Repositories\CourierFreightReconciliationMirrorRepository;
use Tests\Feature\FeatureTestCase;
class CourierFreightReconciliationPageTest extends FeatureTestCase
{
protected function renderFreightPage(bool $summaryReady = true): TestResponse
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = \Mockery::mock(CourierFreightReconciliationMirrorRepository::class);
$repository->shouldReceive('available')->once()->andReturnTrue();
$repository->shouldReceive('ready')->once()->andReturnTrue();
$repository->shouldReceive('paginate')->once()->andReturn([
'data' => [[
'waybill' => '00123456789012345678', 'product_id' => 'ITEM-1',
'send_time' => '2026-09-01 12:00:00', 'transaction_order_no' => 'SO-1',
'province' => '江苏省', 'city' => '常州市', 'district' => '武进区',
'barcode' => 'SKU-1', 'express_name' => '测试快递', 'express_name_2' => '测试网点',
'quantity' => 2, 'product_name' => '验收商品', 'platform' => '测试平台',
'shop_name' => '验收店铺', 'warehouse' => '验收仓库', 'volume' => 7161,
'supplier' => '验收供应商', 'length' => 11, 'width' => 21, 'height' => 31,
'freight' => 8.8, 'reconciliation_weight' => 0.7, 'reconciliation_volume' => 7161,
]],
'total' => $summaryReady ? 1 : null, 'has_more' => false,
'summary' => $summaryReady ? ['count' => 1, 'freight' => 8.8] : null,
'sync' => ['code' => 'fresh', 'last_succeeded_at' => '2026-09-09 10:00:00', 'lag_minutes' => 0],
]);
$this->app->instance(CourierFreightReconciliationMirrorRepository::class, $repository);
return $this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables', 'page' => 'freight-reconciliation',
]));
}
public function test_rendered_values_match_their_column_headings(): void
{
$response = $this->renderFreightPage()->assertOk();
$document = new \DOMDocument();
$previous = libxml_use_internal_errors(true);
$document->loadHTML('<?xml encoding="UTF-8">' . $response->getContent());
libxml_clear_errors();
libxml_use_internal_errors($previous);
$xpath = new \DOMXPath($document);
$headers = $xpath->query('//table[contains(@class,"recon-table")]/thead/tr/th');
$values = $xpath->query('//table[contains(@class,"recon-table")]/tbody/tr[1]/td');
$this->assertCount(23, $headers);
$this->assertCount(23, $values);
$row = [];
foreach ($headers as $index => $header) $row[trim($header->textContent)] = trim($values->item($index)->textContent);
$this->assertSame('7161', $row['体积(cm3)']);
$this->assertSame('验收供应商', $row['供应商']);
$this->assertSame('11', $row['长(cm)']);
$this->assertSame('21', $row['宽(cm)']);
$this->assertSame('31', $row['高(cm)']);
$this->assertSame('8.80', $row['运费']);
$this->assertSame('00123456789012345678', $row['快递单号']);
}
public function test_rows_remain_available_while_the_complete_summary_is_pending(): void
{
$this->renderFreightPage(false)->assertOk()
->assertSeeText('验收商品')
->assertSeeText('正在计算完整筛选汇总')
->assertSee('data-summary-ready="false"', false)
->assertSee('data-summary-count>—', false);
}
public function test_summary_request_keeps_filters_and_returns_only_the_summary(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = \Mockery::mock(CourierFreightReconciliationMirrorRepository::class);
$repository->shouldReceive('requestSummary')->once()
->withArgs(fn (array $filters) => $filters['month'] === '2026-09' && $filters['express_no'] === 'YT')
->andReturn(['count' => 48, 'freight' => 8.8, 'computed_at' => '2026-09-09 10:00:00']);
$this->app->instance(CourierFreightReconciliationMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables', 'page' => 'freight-reconciliation',
'courier_summary' => 1, 'month' => '2026-09', 'express_no' => ' YT ',
]))->assertOk()->assertJsonPath('data.count', 48)->assertJsonPath('data.freight', 8.8);
}
public function test_busy_summary_returns_pending_without_starting_another_calculation(): void
{
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
$repository = \Mockery::mock(CourierFreightReconciliationMirrorRepository::class);
$repository->shouldReceive('requestSummary')->once()->andReturnNull();
$this->app->instance(CourierFreightReconciliationMirrorRepository::class, $repository);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables', 'page' => 'freight-reconciliation', 'courier_summary' => 1,
]))->assertStatus(202)->assertJsonPath('data', null)->assertHeader('Content-Length', '13')->assertHeader('X-Accel-Buffering', 'no');
}
public function test_summary_is_not_available_without_login(): void
{
$repository = \Mockery::mock(CourierFreightReconciliationMirrorRepository::class);
$repository->shouldNotReceive('requestSummary');
$this->app->instance(CourierFreightReconciliationMirrorRepository::class, $repository);
$this->withExceptionHandling()->get(route('business.pages.show', [
'company_id' => $this->company->id,
'section' => 'courier-payables', 'page' => 'freight-reconciliation', 'courier_summary' => 1,
]))->assertRedirect();
}
}