CaiWuXiTong/tests/Unit/EcommerceFinance/DingTalkWorklogClientTest.php

127 lines
4.7 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Modules\EcommerceFinance\Exceptions\DingTalkWorklogException;
use Modules\EcommerceFinance\Services\DingTalkWorklogClient;
use Tests\TestCase;
class DingTalkWorklogClientTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
Cache::flush();
config([
'dingtalk.client_id' => 'test-client',
'dingtalk.client_secret' => 'test-secret',
'dingtalk.app_token_url' => 'https://example.test/token',
'dingtalk.timeout' => 3,
'dingtalk.worklog.template_name' => '财务日报',
'dingtalk.worklog.page_size' => 2,
'dingtalk.worklog.max_pages' => 10,
]);
}
public function test_reports_are_read_across_pages_and_deduplicated(): void
{
Http::fake(function (Request $request) {
if (str_starts_with($request->url(), 'https://example.test/token')) {
return Http::response([
'errcode' => 0,
'access_token' => 'test-token',
'expires_in' => 7200,
]);
}
$cursor = (int) ($request->data()['cursor'] ?? 0);
if ($cursor === 0) {
return Http::response([
'errcode' => 0,
'result' => [
'data_list' => [
[
'report_id' => 'report-a',
'creator_name' => '秋香',
'creator_userid' => 'user-a',
'template_name' => '财务日报',
'create_time' => 1793768760000,
],
[
'report_id' => 'report-b',
'creator_name' => '李斯',
'creator_id' => 'user-b',
'template_name' => '财务日报',
'create_time' => 1793772000000,
],
],
'has_more' => true,
'next_cursor' => 2,
],
]);
}
return Http::response([
'errcode' => 0,
'result' => [
'data_list' => [[
'report_id' => 'report-b',
'creator_name' => '李斯',
'creator_id' => 'user-b',
'template_name' => '财务日报',
'create_time' => 1793772000000,
]],
'has_more' => false,
'next_cursor' => 0,
],
]);
});
$result = app(DingTalkWorklogClient::class)->listReports(
Carbon::parse('2026-10-01 00:00:00', 'Asia/Shanghai'),
Carbon::parse('2026-11-05 23:59:59', 'Asia/Shanghai'),
'财务日报',
);
$this->assertSame(2, $result['pages']);
$this->assertSame(['report-a', 'report-b'], array_column($result['reports'], 'report_id'));
Http::assertSentCount(3);
Http::assertSent(static fn (Request $request): bool =>
str_contains($request->url(), '/topapi/report/list?access_token=test-token')
&& ($request->data()['template_name'] ?? null) === '财务日报'
&& ($request->data()['size'] ?? null) === 2
);
}
public function test_missing_report_query_permission_has_a_stable_error_code(): void
{
Http::fake([
'https://example.test/token*' => Http::response([
'errcode' => 0,
'access_token' => 'test-token',
]),
'https://oapi.dingtalk.com/topapi/report/list*' => Http::response([
'errcode' => 88,
'subcode' => 60011,
'errmsg' => 'missing permission: qyapi_report_query',
]),
]);
try {
app(DingTalkWorklogClient::class)->listReports(
Carbon::parse('2026-10-01 00:00:00', 'Asia/Shanghai'),
Carbon::parse('2026-11-05 23:59:59', 'Asia/Shanghai'),
'财务日报',
);
$this->fail('缺少日志查询权限时应抛出异常。');
} catch (DingTalkWorklogException $exception) {
$this->assertSame('dingtalk_worklog_permission_required', $exception->errorCode);
}
}
}