CaiWuXiTong/tests/Feature/Business/OrderDataPagesUpstreamTest.php

198 lines
8.7 KiB
PHP

<?php
namespace Tests\Feature\Business;
use App\Models\Auth\Permission;
use Mockery;
use Modules\EcommerceFinance\Repositories\OrderDataMirrorRepository;
use Modules\EcommerceFinance\Services\UpstreamQueryCache;
use Modules\EcommerceFinance\Services\UpstreamQueryCacheFactory;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Tests\Feature\FeatureTestCase;
class OrderDataPagesUpstreamTest extends FeatureTestCase
{
protected function setUp(): void
{
parent::setUp();
$mirror = Mockery::mock(OrderDataMirrorRepository::class);
$mirror->shouldReceive('ready')->zeroOrMoreTimes()->andReturnFalse();
$mirror->shouldReceive('promotionReady')->zeroOrMoreTimes()->andReturnFalse();
$this->app->instance(OrderDataMirrorRepository::class, $mirror);
}
public function test_after_sales_prefers_complete_business_mirror_without_registering_a_snapshot(): void
{
$this->allowOrderDataPages();
$mirror = Mockery::mock(OrderDataMirrorRepository::class);
$mirror->shouldReceive('ready')->once()->andReturnTrue();
$mirror->shouldReceive('afterSales')->once()->andReturn(['rows' => [[
'internal_order_no' => 'MIRROR-ORDER-1',
'shop_name' => '共享镜像店铺',
'product_amount' => 88.5,
]] ]);
$this->app->instance(OrderDataMirrorRepository::class, $mirror);
$factory = Mockery::mock(UpstreamQueryCacheFactory::class);
$factory->shouldNotReceive('forSource');
$this->app->instance(UpstreamQueryCacheFactory::class, $factory);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'order-data', 'page' => 'raw-data', 'tab' => 'after-sales-expenses',
]))->assertOk()
->assertSeeText('MIRROR-ORDER-1')
->assertSeeText('共享镜像店铺')
->assertSeeText('MIRROR');
}
public function test_order_data_pages_render_cached_upstream_rows_and_filters(): void
{
$this->allowOrderDataPages();
$cache = Mockery::mock(UpstreamQueryCache::class);
$cache->shouldReceive('remember')->twice()->andReturnUsing(
function (string $scope, array $parameters): array {
if ($scope === 'order-data.after-sales.list') {
$this->assertSame('ORDER-1', $parameters['filters']['order_no']);
return ['rows' => [[
'internal_order_no' => 'ORDER-1',
'shop_name' => '测试店铺',
'product_amount' => 123.45,
]]];
}
$this->assertSame('order-data.promotion.list', $scope);
return [
'date' => '2026-08-09',
'rows' => [[
'shop_name' => '推广测试店铺',
'product_code' => '=SKU-1',
'promotion_fee' => 9.05,
]],
];
},
);
$cache->shouldReceive('responseHeaders')->twice()->andReturn([
'X-Caiwu-Data-Status' => 'direct',
]);
$factory = Mockery::mock(UpstreamQueryCacheFactory::class);
$factory->shouldReceive('forSource')->twice()->with('operations_replica')->andReturn($cache);
$this->app->instance(UpstreamQueryCacheFactory::class, $factory);
$afterSalesResponse = $this->loginAs()
->get(route('business.pages.show', [
'section' => 'order-data',
'page' => 'raw-data',
'tab' => 'after-sales-expenses',
'order_no' => 'ORDER-1',
'from' => '2026-08-01',
'to' => '2026-08-09',
]));
$afterSalesResponse
->assertOk()
->assertSeeText('ORDER-1')
->assertSeeText('测试店铺')
->assertSeeText('123.45')
->assertSeeText('DIRECT')
->assertSeeText('导出当前页')
->assertSee('id="order-data-from" name="from" type="date" value="2026-08-01"', false)
->assertSee('id="order-data-to" name="to" type="date" value="2026-08-09"', false)
->assertSee('data-date-picker-contract="order-data-after-sales-date-picker"', false)
->assertSee('data-date-picker-input="order-data-from"', false)
->assertSee('aria-label="选择订单开始日期"', false)
->assertSee('data-date-picker-input="order-data-to"', false)
->assertSee('aria-label="选择订单结束日期"', false)
->assertSeeText('calendar_today')
->assertSee("typeof input.showPicker === 'function'", false)
->assertSee('id="order-data-after-sales-export-button"', false)
->assertSee('data-export-contract="order-data.after-sales.current-page-export"', false)
->assertSee('data-export-table="order-data-after-sales-table"', false)
->assertSee('data-export-value="ORDER-1"', false)
->assertSee('data-export-value="123.45"', false)
->assertSee('data-export-number="true"', false)
->assertSee('window.setTimeout(() => {', false)
->assertSee('URL.revokeObjectURL(url);', false)
->assertSee('订单售后费用明细_2026-08-01_2026-08-09_第1页.csv', false);
$promotionResponse = $this->get(route('business.pages.show', [
'section' => 'order-data',
'page' => 'raw-data',
'tab' => 'promotion-expenses',
]));
$promotionResponse
->assertOk()
->assertSeeText('推广测试店铺')
->assertSeeText('SKU-1')
->assertSeeText('9.05')
->assertSee('value="2026-08-09"', false)
->assertSee('id="order-data-promotion-export-button"', false)
->assertSee('data-export-contract="order-data.promotion.current-page-export"', false)
->assertSee('data-export-table="order-data-promotion-table"', false)
->assertSee('data-export-value="=SKU-1"', false)
->assertSee('data-export-value="9.05"', false)
->assertSee('data-export-number="true"', false)
->assertSee('protectSpreadsheetFormula', false)
->assertSee('URL.revokeObjectURL(url);', false)
->assertSee('商品推广费用明细_2026-08-09_第1页.csv', false);
}
public function test_order_data_page_keeps_rendering_when_the_upstream_is_unavailable(): void
{
$this->allowOrderDataPages();
$cache = Mockery::mock(UpstreamQueryCache::class);
$cache->shouldReceive('remember')->once()->andThrow(
new ServiceUnavailableHttpException(30, '首份共享快照正在准备。')
);
$factory = Mockery::mock(UpstreamQueryCacheFactory::class);
$factory->shouldReceive('forSource')->once()->with('operations_replica')->andReturn($cache);
$this->app->instance(UpstreamQueryCacheFactory::class, $factory);
$this->loginAs()
->get(route('business.pages.show', [
'section' => 'order-data',
'page' => 'raw-data',
'tab' => 'promotion-expenses',
]))
->assertOk()
->assertSeeText('首份共享快照正在准备。')
->assertSeeText('暂无数据')
->assertSee('id="order-data-promotion-export-button"', false)
->assertSee('disabled="disabled"', false);
}
public function test_after_sales_export_is_disabled_when_the_current_page_has_no_rows(): void
{
$this->allowOrderDataPages();
$cache = Mockery::mock(UpstreamQueryCache::class);
$cache->shouldReceive('remember')->once()->andReturn(['rows' => []]);
$cache->shouldReceive('responseHeaders')->once()->andReturn([
'X-Caiwu-Data-Status' => 'direct',
]);
$factory = Mockery::mock(UpstreamQueryCacheFactory::class);
$factory->shouldReceive('forSource')->once()->with('operations_replica')->andReturn($cache);
$this->app->instance(UpstreamQueryCacheFactory::class, $factory);
$this->loginAs()
->get(route('business.pages.show', [
'section' => 'order-data',
'page' => 'raw-data',
'tab' => 'after-sales-expenses',
]))
->assertOk()
->assertSeeText('暂无数据')
->assertSeeText('导出当前页')
->assertSee('id="order-data-after-sales-export-button"', false)
->assertSee('disabled="disabled"', false);
}
private function allowOrderDataPages(): void
{
$this->user->update(['locale' => 'zh-CN']);
$this->user->attachPermission(
Permission::where('name', 'read-admin-panel')->firstOrFail()
);
}
}