Files
huangjingfen/pro_v3.5.1_副本/tests/hjf/SmokeTest.php

327 lines
12 KiB
PHP
Raw Normal View History

feat(fsgx): 完成全部24项开发任务 Phase1-7 Phase1 后端核心: - 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess) - SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机) - StoreOrderCreateServices 周期循环佣金计算 - StoreOrderTakeServices 佣金发放后同步冻结积分 - StoreProductServices/StoreProduct 保存 is_queue_goods Phase2 后端接口: - GET /api/hjf/brokerage/progress 佣金周期进度 - GET /api/hjf/assets/overview 资产总览 - HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务 - PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口 - GET /adminapi/hjf/points/release_log 积分日志接口 Phase3 前端清理: - hjfCustom.js 路由精简(仅保留 points/log) - hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口 - pages.json 公排→推荐佣金/佣金记录/佣金规则 Phase4-5 前端改造: - queue/status.vue 推荐佣金进度页整体重写 - 商品详情/订单确认/支付结果页文案与逻辑改造 - 个人中心/资产页/引导页/规则页文案改造 - HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造 - 推广中心嵌入佣金进度摘要 - hjfMockData.js 全量更新(公排字段→佣金字段) Phase6 Admin 增强: - 用户列表新增 frozen_points/available_points 列及不考核操作按钮 - hjfPoints.js USE_MOCK=false 对接真实积分日志接口 Phase7 配置文档: - docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单 Made-with: Cursor
2026-03-23 22:32:19 +08:00
<?php
declare(strict_types=1);
namespace tests\hjf;
use PHPUnit\Framework\TestCase;
/**
* P4 联调冒烟测试SmokeTest
*
* 使用说明:
* 1. 确保 Phase 2 数据库迁移已执行eb_queue_pool / eb_points_release_log 等表已创建)
* 2. 确保后端服务已启动ThinkPHP 8 + Swoole PHP-FPM
* 3. 设置环境变量:
* HJF_API_BASE=http://127.0.0.1:8080/api
* HJF_ADMIN_BASE=http://127.0.0.1:8080/adminapi
* HJF_TOKEN=<有效用户Token>
* HJF_ADMIN_TOKEN=<有效管理员Token>
* 4. 运行:./vendor/bin/phpunit tests/hjf/SmokeTest.php
*
* 覆盖场景:
* P4-02 UniApp 冒烟:登录后访问公排/资产/积分/会员接口
* P4-03 Admin 冒烟:公排订单列表 / 配置保存 / 会员等级 / 积分日志
* P4-05 定时任务验证:手动调用积分释放 command验证 release_log 有新记录
*
* Class SmokeTest
* @package tests\hjf
*/
class SmokeTest extends TestCase
{
private string $apiBase;
private string $adminBase;
private string $token;
private string $adminToken;
protected function setUp(): void
{
$this->apiBase = rtrim(getenv('HJF_API_BASE') ?: 'http://127.0.0.1:8080/api', '/');
$this->adminBase = rtrim(getenv('HJF_ADMIN_BASE') ?: 'http://127.0.0.1:8080/adminapi', '/');
$this->token = getenv('HJF_TOKEN') ?: '';
$this->adminToken = getenv('HJF_ADMIN_TOKEN') ?: '';
}
// -----------------------------------------------------------------------
// 辅助方法
// -----------------------------------------------------------------------
/**
* 发送 GET 请求,返回解析后的响应体数组
*/
private function get(string $url, string $token = ''): array
{
$headers = ['Content-Type: application/json'];
if ($token) {
$headers[] = "Authorization: Bearer {$token}";
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode((string)$body, true) ?: [];
$data['__http_code'] = $http;
return $data;
}
/**
* 发送 POST 请求,返回解析后的响应体数组
*/
private function post(string $url, array $payload, string $token = ''): array
{
$headers = ['Content-Type: application/json'];
if ($token) {
$headers[] = "Authorization: Bearer {$token}";
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode((string)$body, true) ?: [];
$data['__http_code'] = $http;
return $data;
}
// -----------------------------------------------------------------------
// P4-02 UniApp 冒烟测试
// -----------------------------------------------------------------------
/**
* @test
* P4-02-A: 公排状态接口可访问,返回 200 且包含 total_orders/my_orders/progress 字段
*/
public function testUniAppQueueStatus(): void
{
if (!$this->token) {
$this->markTestSkipped('HJF_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->apiBase}/hjf/queue/status", $this->token);
$this->assertEquals(200, $res['__http_code'], '公排状态接口 HTTP 200');
$this->assertArrayHasKey('data', $res, '响应包含 data 字段');
$data = $res['data'];
$this->assertArrayHasKey('total_orders', $data, 'data 包含 total_orders');
$this->assertArrayHasKey('my_orders', $data, 'data 包含 my_orders');
$this->assertArrayHasKey('progress', $data, 'data 包含 progress');
}
/**
* @test
* P4-02-B: 公排历史接口可访问,返回分页格式
*/
public function testUniAppQueueHistory(): void
{
if (!$this->token) {
$this->markTestSkipped('HJF_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->apiBase}/hjf/queue/history?page=1&limit=10", $this->token);
$this->assertEquals(200, $res['__http_code'], '公排历史接口 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('list', $data, 'data 包含 list');
$this->assertArrayHasKey('count', $data, 'data 包含 count');
}
/**
* @test
* P4-02-C: 资产总览接口,返回余额+积分字段
*/
public function testUniAppAssetsOverview(): void
{
if (!$this->token) {
$this->markTestSkipped('HJF_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->apiBase}/hjf/assets/overview", $this->token);
$this->assertEquals(200, $res['__http_code'], '资产总览接口 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('now_money', $data, 'data 包含 now_money');
$this->assertArrayHasKey('frozen_points', $data, 'data 包含 frozen_points');
$this->assertArrayHasKey('available_points', $data, 'data 包含 available_points');
}
/**
* @test
* P4-02-D: 积分明细接口,返回分页列表
*/
public function testUniAppPointsDetail(): void
{
if (!$this->token) {
$this->markTestSkipped('HJF_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->apiBase}/hjf/points/detail?page=1&limit=10", $this->token);
$this->assertEquals(200, $res['__http_code'], '积分明细接口 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('list', $data, 'data 包含 list');
$this->assertArrayHasKey('count', $data, 'data 包含 count');
}
/**
* @test
* P4-02-E: 会员信息接口,返回 member_level 字段
*/
public function testUniAppMemberInfo(): void
{
if (!$this->token) {
$this->markTestSkipped('HJF_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->apiBase}/hjf/member/info", $this->token);
$this->assertEquals(200, $res['__http_code'], '会员信息接口 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('member_level', $data, 'data 包含 member_level');
$this->assertContains(
(int)($data['member_level'] ?? -1),
[0, 1, 2, 3, 4],
'member_level 取值 0~4'
);
}
// -----------------------------------------------------------------------
// P4-03 Admin 冒烟测试
// -----------------------------------------------------------------------
/**
* @test
* P4-03-A: Admin 公排订单列表接口,返回分页数据
*/
public function testAdminQueueOrderList(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->adminBase}/hjf/queue/order?page=1&limit=10", $this->adminToken);
$this->assertEquals(200, $res['__http_code'], 'Admin 公排订单列表 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('list', $data, 'data 包含 list');
$this->assertArrayHasKey('count', $data, 'data 包含 count');
}
/**
* @test
* P4-03-B: Admin 公排配置读取,返回 hjf_trigger_multiple 等关键字段
*/
public function testAdminQueueConfigGet(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->adminBase}/hjf/queue/config", $this->adminToken);
$this->assertEquals(200, $res['__http_code'], 'Admin 公排配置 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('hjf_trigger_multiple', $data, 'data 包含 hjf_trigger_multiple');
}
/**
* @test
* P4-03-C: Admin 公排配置保存(写回原值,不改变业务数据)
*/
public function testAdminQueueConfigSave(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
// 先读取当前配置
$getRes = $this->get("{$this->adminBase}/hjf/queue/config", $this->adminToken);
$current = $getRes['data'] ?? ['hjf_trigger_multiple' => 4, 'hjf_release_rate' => 4];
// 写回原值
$saveRes = $this->post("{$this->adminBase}/hjf/queue/config", $current, $this->adminToken);
$this->assertEquals(200, $saveRes['__http_code'], 'Admin 公排配置保存 HTTP 200');
}
/**
* @test
* P4-03-D: Admin 会员列表接口,返回分页数据含 member_level
*/
public function testAdminMemberList(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->adminBase}/hjf/member/list?page=1&limit=10", $this->adminToken);
$this->assertEquals(200, $res['__http_code'], 'Admin 会员列表 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('list', $data, 'data 包含 list');
$this->assertArrayHasKey('count', $data, 'data 包含 count');
// 若有记录,验证字段完整性
if (!empty($data['list'])) {
$first = $data['list'][0];
$this->assertArrayHasKey('member_level', $first, 'list[0] 包含 member_level');
$this->assertArrayHasKey('direct_order_count', $first, 'list[0] 包含 direct_order_count');
$this->assertArrayHasKey('umbrella_order_count', $first, 'list[0] 包含 umbrella_order_count');
}
}
/**
* @test
* P4-03-E: Admin 积分释放日志接口,返回分页数据
*/
public function testAdminPointsReleaseLog(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
$res = $this->get("{$this->adminBase}/hjf/points/release-log?page=1&limit=10", $this->adminToken);
$this->assertEquals(200, $res['__http_code'], 'Admin 积分释放日志 HTTP 200');
$data = $res['data'] ?? [];
$this->assertArrayHasKey('list', $data, 'data 包含 list');
$this->assertArrayHasKey('count', $data, 'data 包含 count');
}
// -----------------------------------------------------------------------
// P4-05 定时任务验证(积分每日释放)
// -----------------------------------------------------------------------
/**
* @test
* P4-05: 手动触发 Artisan/Think 积分释放命令后release_log 有新记录
*
* 验证方式:
* 1. 记录触发前的日志总数
* 2. 调用 Admin 接口触发(或本地 CLIphp think hjf:release-points
* 3. 等待队列消费最多10秒
* 4. 再次查询日志总数,新增量 >= 1
*/
public function testDailyPointsReleaseCreatesLogs(): void
{
if (!$this->adminToken) {
$this->markTestSkipped('HJF_ADMIN_TOKEN 未设置,跳过');
}
// 触发前的日志总数
$before = $this->get("{$this->adminBase}/hjf/points/release-log?page=1&limit=1", $this->adminToken);
$countBefore = (int)($before['data']['count'] ?? 0);
// 触发定时任务(通过 CLI实际测试时需在后端服务器执行
// 此处记录预期行为:执行后 count 应增加
// 若在 CI 环境中可替换为shell_exec('php think hjf:release-points');
// 由于无法在 PHPUnit 内部确保队列消费完成,此测试标记为 skipped 并记录说明
$this->markTestIncomplete(
"P4-05 定时任务测试需在后端服务器手动执行:\n" .
" php think hjf:release-points\n" .
"执行后再运行本测试检验 release_log count 从 {$countBefore} 增加。\n" .
"若 frozen_points 为0的用户较多释放量可能为0属正常行为"
);
}
}