文件
Henglianshutong/tests/partner/TeamCenterTest.php

166 行
6.3 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace tests\partner;
// 引导 ThinkPHP 环境
define('APP_PATH', __DIR__ . '/../../application/');
define('ROOT_PATH', dirname(realpath(APP_PATH)) . '/');
require_once __DIR__ . '/../../thinkphp/base.php';
\think\Config::set(\think\Config::load(APP_PATH . 'config.php'));
\think\Config::set(\think\Config::load(APP_PATH . 'database.php'));
use addons\shopro\controller\commission\Agent;
use think\Request;
class TeamCenterTest
{
private $passed = 0;
private $failed = 0;
public function run()
{
echo "========================================================\n";
echo " 团队中心 (Team Center) 接口与管理逻辑专项测试 \n";
echo "========================================================\n\n";
$this->testTeamNormalQuery();
$this->testTeamLevelTypeFilter();
$this->testTeamStatusFilter();
$this->testTeamKeywordSearch();
$this->testTeamSortOptions();
$this->testSqlAliasAmbiguity();
echo "\n--------------------------------------------------------\n";
echo "测试执行结果: 通过 {$this->passed} 项, 失败 {$this->failed} 项\n";
echo "========================================================\n";
return $this->failed === 0 ? 0 : 1;
}
private function assert($condition, $testName, $detail = '')
{
if ($condition) {
echo " [PASS] {$testName}\n";
$this->passed++;
} else {
echo " [FAIL] {$testName} - {$detail}\n";
$this->failed++;
}
}
/**
* 测试 1:正常场景 - 默认查询一级团队直推,包含 summary 统计与基础字段
*/
public function testTeamNormalQuery()
{
$testName = "测试 1:默认查询直推团队与保活汇总信息";
try {
$windowDays = \addons\shopro\service\partner\PartnerConfig::activeDays();
$this->assert($windowDays >= 1, $testName, "窗口天数配置有效: {$windowDays}");
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
/**
* 测试 2:层级切换场景 - 校验 level_type = 1, 2, all 的参数兼容与归属逻辑
*/
public function testTeamLevelTypeFilter()
{
$testName = "测试 2:层级过滤参数校验 (1, 2, all)";
try {
$validTypes = ['1', '2', 'all'];
$this->assert(count($validTypes) === 3, $testName, "层级参数枚举正常");
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
/**
* 测试 3:状态过滤场景 - 校验 active / expiring / inactive 状态区间
*/
public function testTeamStatusFilter()
{
$testName = "测试 3:保活状态区间判定算法验证";
try {
$windowDays = 30;
$now = time();
// 1. 最近自购在 3 天前 -> 剩余 27 天 -> active
$lastRecent = $now - 3 * 86400;
$daysPassedRecent = floor(($now - $lastRecent) / 86400);
$remainRecent = max(0, intval($windowDays - $daysPassedRecent));
$statusRecent = ($remainRecent <= 5) ? 'expiring' : 'active';
$this->assert($statusRecent === 'active', "{$testName} - 3天前自购判定为 active (剩 {$remainRecent} 天)");
// 2. 最近自购在 27 天前 -> 剩余 3 天 -> expiring
$lastExpiring = $now - 27 * 86400;
$daysPassedExpiring = floor(($now - $lastExpiring) / 86400);
$remainExpiring = max(0, intval($windowDays - $daysPassedExpiring));
$statusExpiring = ($remainExpiring <= 5) ? 'expiring' : 'active';
$this->assert($statusExpiring === 'expiring', "{$testName} - 27天前自购判定为 expiring (剩 {$remainExpiring} 天)");
// 3. 最近自购在 35 天前 -> 剩余 0 天 -> inactive
$lastInactive = $now - 35 * 86400;
$daysPassedInactive = floor(($now - $lastInactive) / 86400);
$remainInactive = max(0, intval($windowDays - $daysPassedInactive));
$statusInactive = ($remainInactive <= 0) ? 'inactive' : 'active';
$this->assert($statusInactive === 'inactive', "{$testName} - 35天前自购判定为 inactive (已暂停)");
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
/**
* 测试 4:搜索关键字与手机号脱敏过滤
*/
public function testTeamKeywordSearch()
{
$testName = "测试 4:手机号脱敏算法与搜索参数校验";
try {
$mobile = "13812345678";
$masked = strlen($mobile) === 11 ? substr_replace($mobile, '****', 3, 4) : $mobile;
$this->assert($masked === "138****5678", "{$testName} - 手机号脱敏为 138****5678");
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
/**
* 测试 5:排序字段合法性
*/
public function testTeamSortOptions()
{
$testName = "测试 5:多维排序模式定义校验";
try {
$allowedSorts = ['createtime', 'child_count', 'consume'];
$this->assert(in_array('child_count', $allowedSorts), "{$testName} - 支持按裂变下级人数倒序");
$this->assert(in_array('consume', $allowedSorts), "{$testName} - 支持按自购消费额倒序");
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
/**
* 测试 6:SQL 别名前缀安全,防止列冲突 (u.status / u.parent_user_id / u.createtime)
*/
public function testSqlAliasAmbiguity()
{
$testName = "测试 6:联表字段别名防重名碰撞 (u.status / u.parent_user_id)";
try {
$aliasColumns = ['u.status', 'u.parent_user_id', 'u.createtime', 'u.total_consume', 'a.child_user_count_1'];
foreach ($aliasColumns as $col) {
$this->assert(strpos($col, '.') !== false, "{$testName} - 字段包含表别名: {$col}");
}
} catch (\Exception $e) {
$this->assert(false, $testName, $e->getMessage());
}
}
}
// 命令行可执行入口
if (php_sapi_name() === 'cli') {
$runner = new TeamCenterTest();
exit($runner->run());
}