221 lines
9.4 KiB
PHP
221 lines
9.4 KiB
PHP
<?php
|
||
|
||
namespace Tests\Feature\Business;
|
||
|
||
use App\Models\Auth\Permission;
|
||
use Illuminate\Support\Facades\Http;
|
||
use Mockery;
|
||
use Modules\EcommerceFinance\Repositories\DingPayableWorkflowMirrorRepository;
|
||
use Tests\Feature\FeatureTestCase;
|
||
|
||
class DingPayableWorkflowPageTest extends FeatureTestCase
|
||
{
|
||
public function test_cloud_warehouse_vehicle_fee_page_renders_all_workflow_sections(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('paginate')->once()->andReturn([
|
||
'data' => [[
|
||
'process_instance_id' => 'PROC-TEST-001',
|
||
'workflow' => [
|
||
'businessId' => '202607031324000376786',
|
||
'title' => '应付申请流程',
|
||
'status' => 'COMPLETED',
|
||
'result' => 'agree',
|
||
'originatorUserId' => 'user-1',
|
||
'originatorUserName' => '扬灵',
|
||
'originatorDeptName' => '财务部',
|
||
'createAt' => '2026-08-28 10:00:00',
|
||
'finishTime' => '2026-08-28 11:00:00',
|
||
],
|
||
'detail' => ['类型' => '快递运费', '用途' => '拉到江西仓的车费', '付款金额' => '1200'],
|
||
'fields' => [
|
||
'应付明细' => [],
|
||
'付款明细' => [['付款金额' => '1200']],
|
||
'附件' => '',
|
||
'未签字版合同附件或其他明细附件' => [[
|
||
'spaceId' => '369334649',
|
||
'fileName' => '测试对账附件.xlsx',
|
||
'fileId' => '123456',
|
||
'fileType' => 'xlsx',
|
||
]],
|
||
],
|
||
'tasks' => [['status' => 'COMPLETED']],
|
||
]],
|
||
'total' => 1,
|
||
'status' => 'succeeded',
|
||
'last_synced_at' => '2026-08-28 11:05:00',
|
||
]);
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
$this->loginAs()->get(route('business.pages.show', [
|
||
'section' => 'courier-payables',
|
||
'page' => 'payable-cloud-warehouse-vehicle-fee',
|
||
]))->assertOk()
|
||
->assertSee('应付云仓车费')
|
||
->assertSee('钉钉审批编号')
|
||
->assertSee('202607031324000376786')
|
||
->assertSee('扬灵')
|
||
->assertSee('已完成')
|
||
->assertSee('拉到江西仓的车费')
|
||
->assertSee('用途同时包含“仓”“车费”')
|
||
->assertDontSeeText('全部表单字段')
|
||
->assertDontSeeText('付款明细')
|
||
->assertDontSeeText('审批任务')
|
||
->assertSee('测试对账附件.xlsx')
|
||
->assertSee('process_instance_id=PROC-TEST-001', false)
|
||
->assertSee('file_id=123456', false)
|
||
->assertSee('ding-payable-attachment"', false)
|
||
->assertSee('data-ding-payable-row', false)
|
||
->assertSee('is-clickable', false)
|
||
->assertSee('is-active', false)
|
||
->assertSee('镜像状态:succeeded');
|
||
}
|
||
|
||
public function test_cloud_warehouse_vehicle_fee_page_uses_ding_talk_rejection_result(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('paginate')->once()->andReturn([
|
||
'data' => [[
|
||
'process_instance_id' => 'PROC-TEST-REJECTED',
|
||
'workflow' => [
|
||
'businessId' => '202608291446000258827',
|
||
'title' => '应付申请流程',
|
||
'status' => 'COMPLETED',
|
||
'result' => 'refuse',
|
||
'originatorUserId' => 'user-1',
|
||
'originatorUserName' => '扬灵',
|
||
],
|
||
'detail' => ['类型' => '快递运费', '用途' => '拉到江西仓的车费'],
|
||
'fields' => [],
|
||
'tasks' => [],
|
||
]],
|
||
'total' => 1,
|
||
'status' => 'succeeded',
|
||
'last_synced_at' => '2026-08-31 13:42:04',
|
||
]);
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
$this->loginAs()->get(route('business.pages.show', [
|
||
'section' => 'courier-payables',
|
||
'page' => 'payable-cloud-warehouse-vehicle-fee',
|
||
]))->assertOk()
|
||
->assertSee('<td>已拒绝</td>', false)
|
||
->assertDontSee('<td>已完成</td>', false)
|
||
->assertSee('已拒绝');
|
||
}
|
||
|
||
public function test_cloud_warehouse_vehicle_fee_page_keeps_an_unavailable_mirror_readable(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('paginate')->andThrow(new \RuntimeException('not ready'));
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
$this->loginAs()->get(route('business.pages.show', [
|
||
'section' => 'courier-payables',
|
||
'page' => 'payable-cloud-warehouse-vehicle-fee',
|
||
]))->assertOk()
|
||
->assertSee('钉钉应付流程镜像尚未完成同步,请稍后重试。')
|
||
->assertSee('镜像读取失败,请稍后重试。');
|
||
}
|
||
|
||
public function test_cloud_warehouse_vehicle_fee_page_passes_workflow_time_and_status_filters(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('paginate')->once()->with(
|
||
[
|
||
'process_instance_id' => '',
|
||
'created_from' => '2026-07-01',
|
||
'finished_to' => '2026-07-31',
|
||
'status' => 'COMPLETED',
|
||
],
|
||
1,
|
||
Mockery::type('int'),
|
||
)->andReturn([
|
||
'data' => [],
|
||
'total' => 0,
|
||
'status' => 'succeeded',
|
||
'last_synced_at' => '2026-08-29 10:11:24',
|
||
]);
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
$this->loginAs()->get(route('business.pages.show', [
|
||
'section' => 'courier-payables',
|
||
'page' => 'payable-cloud-warehouse-vehicle-fee',
|
||
'created_from' => '2026-07-01',
|
||
'finished_to' => '2026-07-31',
|
||
'status' => 'completed',
|
||
]))->assertOk()
|
||
->assertSee('流程时间(创建时间至完成时间)')
|
||
->assertSee('2026-07-01')
|
||
->assertSee('2026-07-31')
|
||
->assertSee('状态')
|
||
->assertSee('全部状态');
|
||
}
|
||
|
||
public function test_attachment_download_streams_dingtalk_file(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
|
||
config([
|
||
'dingtalk.client_id' => 'test-client-id',
|
||
'dingtalk.client_secret' => 'test-client-secret',
|
||
]);
|
||
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('attachment')
|
||
->once()
|
||
->with('PROC-TEST-001', '123456')
|
||
->andReturn(['fileName' => '测试对账附件.xlsx', 'fileType' => 'xlsx', 'fileSize' => 9]);
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
Http::fake([
|
||
'oapi.dingtalk.com/*' => Http::response(['access_token' => 'test-token']),
|
||
'api.dingtalk.com/*' => Http::response([
|
||
'success' => true,
|
||
'result' => ['downloadUri' => 'https://fake-oss.example.com/file'],
|
||
]),
|
||
'fake-oss.example.com/*' => Http::response('file-bytes', 200, ['Content-Type' => 'application/octet-stream']),
|
||
]);
|
||
|
||
$response = $this->loginAs()->get(route('business.courier-payables.ding-payable-attachment.download', [
|
||
'process_instance_id' => 'PROC-TEST-001',
|
||
'file_id' => '123456',
|
||
]));
|
||
|
||
$response->assertOk()
|
||
->assertHeader('content-type', 'application/octet-stream');
|
||
|
||
$this->assertSame('file-bytes', $response->streamedContent());
|
||
$this->assertStringContainsString(
|
||
rawurlencode('测试对账附件.xlsx'),
|
||
(string) $response->headers->get('content-disposition'),
|
||
);
|
||
}
|
||
|
||
public function test_attachment_download_rejects_unknown_file(): void
|
||
{
|
||
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
|
||
|
||
$repository = Mockery::mock(DingPayableWorkflowMirrorRepository::class);
|
||
$repository->shouldReceive('attachment')->once()->andReturn(null);
|
||
$this->app->instance(DingPayableWorkflowMirrorRepository::class, $repository);
|
||
|
||
Http::fake();
|
||
|
||
$this->loginAs()
|
||
->withExceptionHandling()
|
||
->withHeaders(['X-Requested-With' => 'XMLHttpRequest'])
|
||
->get(route('business.courier-payables.ding-payable-attachment.download', [
|
||
'process_instance_id' => 'PROC-UNKNOWN',
|
||
'file_id' => '999',
|
||
]))
|
||
->assertNotFound();
|
||
|
||
Http::assertNothingSent();
|
||
}
|
||
}
|