Merge branch release/21.7.6 of zentao/zentaopms (#11926)

This commit is contained in:
刘刚
2025-10-20 09:46:26 +08:00
committed by Gitfox
8 changed files with 24 additions and 697 deletions
@@ -1,99 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 convertTao::createWorkflowAction();
timeout=0
cid=0
- 测试步骤1:空relations数组输入情况 >> 期望返回空数组
- 测试步骤2:包含普通键值对的relations >> 期望正常返回relations
- 测试步骤3:包含zentaoAction键的relations >> 期望处理zentaoAction相关逻辑
- 测试步骤4:包含add_action值的zentaoAction >> 期望触发workflow创建逻辑
- 测试步骤5:同时传入jiraActions参数 >> 期望正确处理两个参数的协同
- 测试步骤6:包含多个zentaoAction键的复杂relations >> 期望处理复杂场景
*/
// 简单的测试框架函数
function r($result) {
global $testResult;
$testResult = $result;
return true;
}
function p($path = '') {
global $testResult, $checkPath;
$checkPath = $path;
return true;
}
function e($expected) {
global $testResult, $checkPath;
if($checkPath == '') {
$actual = $testResult;
} else {
$pathParts = explode(':', $checkPath);
$actual = $testResult;
foreach($pathParts as $part) {
if(is_array($actual) && isset($actual[$part])) {
$actual = $actual[$part];
} else {
$actual = null;
break;
}
}
}
if($actual === $expected) {
echo "PASS\n";
return true;
} else {
echo "FAIL - Expected: ";
var_export($expected);
echo ", Actual: ";
var_export($actual);
echo "\n";
return false;
}
}
class convertWorkflowActionTest
{
private $config;
public function __construct()
{
// 模拟开源版本配置
$this->config = new stdclass();
$this->config->edition = 'open';
}
/**
* Test createWorkflowAction method for open edition.
*
* @param array $relations
* @param array $jiraActions
* @access public
* @return array
*/
public function createWorkflowActionTest($relations = array(), $jiraActions = array())
{
// 模拟open版本的逻辑:直接返回relations
if($this->config->edition == 'open') return $relations;
// 这里省略企业版逻辑,因为测试环境无法支持
return $relations;
}
}
$convertTest = new convertWorkflowActionTest();
r($convertTest->createWorkflowActionTest(array(), array())) && p() && e(array());
r($convertTest->createWorkflowActionTest(array('test' => 'value'), array())) && p('test') && e('value');
r($convertTest->createWorkflowActionTest(array('zentaoActionbug' => array('action1' => 'other_action')), array())) && p('zentaoActionbug:action1') && e('other_action');
r($convertTest->createWorkflowActionTest(array('zentaoActionbug' => array('newaction1' => 'add_action')), array('action1' => 'jira_action'))) && p('zentaoActionbug:newaction1') && e('add_action');
r($convertTest->createWorkflowActionTest(array('normalKey' => 'value', 'zentaoActionbug' => array('action1' => 'test')), array('action1' => 'test_action'))) && p('normalKey') && e('value');
r($convertTest->createWorkflowActionTest(array('zentaoActionbug' => array('action1' => 'test'), 'zentaoActiontask' => array('action2' => 'test2')), array())) && p('zentaoActionbug:action1') && e('test');
+12 -3
View File
@@ -9,6 +9,9 @@ cid=0
- 步骤1:空toList列表情况 @0
- 步骤2:toList包含有效用户但emails为空 @0
- 步骤3:正常情况添加有效邮件地址第admin条的sended属性 @1
- 步骤4:邮件地址已标记为已发送第admin条的sended属性 @1
- 步骤5:无效邮件地址情况第invalid条的sended属性 @~~
*/
@@ -25,6 +28,12 @@ $mailTest = new mailTest();
// 4. 测试步骤执行(每个r()...e()语句必须在同一行)
r(count($mailTest->setTOTest(array(), array()))) && p() && e('0'); // 步骤1:空toList列表情况
r(count($mailTest->setTOTest(array('admin'), array()))) && p() && e('0'); // 步骤2:toList包含有效用户但emails为空
$emails = array(); $emails['admin'] = new stdclass(); $emails['admin']->email = 'admin@cnezsoft.com'; $emails['admin']->realname = '管理员'; r($mailTest->setTOTest(array('admin'), $emails)) && p('admin:sended') && e('1'); // 步骤3:正常情况添加有效邮件地址
$emails = array(); $emails['admin'] = new stdclass(); $emails['admin']->email = 'admin@cnezsoft.com'; $emails['admin']->realname = '管理员'; $emails['admin']->sended = true; r($mailTest->setTOTest(array('admin'), $emails)) && p('admin:sended') && e('1'); // 步骤4:邮件地址已标记为已发送
$emails = array(); $emails['invalid'] = new stdclass(); $emails['invalid']->email = 'invalid-email'; $emails['invalid']->realname = '无效用户'; r($mailTest->setTOTest(array('invalid'), $emails)) && p('invalid:sended') && e('~~'); // 步骤5:无效邮件地址情况
$emails = ['admin' => (object)['email' => 'admin@cnezsoft.com', 'realname' => '管理员']];
r($mailTest->setTOTest(array('admin'), $emails)) && p('admin:sended') && e('1'); // 步骤3:正常情况添加有效邮件地址
$emails = ['admin' => (object)['email' => 'admin@cnezsoft.com', 'realname' => '管理员', 'sended' => true]];
r($mailTest->setTOTest(array('admin'), $emails)) && p('admin:sended') && e('1'); // 步骤4:邮件地址已标记为已发送
$emails = ['invalid' => (object)['email' => 'invalid-email', 'realname' => '无效用户']];
r($mailTest->setTOTest(array('invalid'), $emails)) && p('invalid:sended') && e('~~'); // 步骤5:无效邮件地址情况
-157
View File
@@ -1,157 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 mailTao::getObjectTitle();
timeout=0
cid=0
0
0
测试单1
文档标题1
用户需求版本一1
BUG1
开发任务12
*/
// 简化的测试框架函数
$_result = null;
function r($result) {
global $_result;
$_result = $result;
return true;
}
function p($keys = '') {
global $_result;
if(empty($_result)) {
echo '0' . "\n";
} else {
echo $_result . "\n";
}
return true;
}
function e($expect) {
// 在简化版本中,e函数只是占位符
return true;
}
/**
* 模拟mailTao测试类,避免环境依赖
*/
class mailTaoTest
{
/**
* 测试getObjectTitle方法
*
* @param object $object
* @param string $objectType
* @access public
* @return string
*/
public function getObjectTitleTest($object, $objectType)
{
// 实现getObjectTitle方法的核心逻辑
if(empty($objectType)) return '';
// 模拟action配置中的objectNameFields
$objectNameFields = array(
'product' => 'name',
'productline' => 'name',
'epic' => 'title',
'story' => 'title',
'requirement' => 'title',
'productplan' => 'title',
'release' => 'name',
'program' => 'name',
'project' => 'name',
'execution' => 'name',
'task' => 'name',
'build' => 'name',
'bug' => 'title',
'testcase' => 'title',
'case' => 'title',
'testtask' => 'name',
'user' => 'account',
'api' => 'title',
'board' => 'name',
'boardspace' => 'name',
'doc' => 'title',
'doclib' => 'name',
'docspace' => 'name',
'doctemplate' => 'title',
'todo' => 'name',
'branch' => 'name',
'module' => 'name',
'testsuite' => 'name',
'caselib' => 'name',
'testreport' => 'title',
'entry' => 'name',
'webhook' => 'name',
'risk' => 'name',
'issue' => 'title',
'design' => 'name',
'stakeholder' => 'user',
'budget' => 'name',
'job' => 'name',
'team' => 'name',
'pipeline' => 'name',
'mr' => 'title',
'reviewcl' => 'title',
'kanbancolumn' => 'name',
'kanbanlane' => 'name',
'kanbanspace' => 'name',
'kanbanregion' => 'name',
'kanban' => 'name',
'kanbancard' => 'name'
);
$nameField = isset($objectNameFields[$objectType]) ? $objectNameFields[$objectType] : '';
if(empty($nameField)) return '';
return isset($object->$nameField) ? $object->$nameField : '';
}
}
$mailTest = new mailTaoTest();
// 创建测试用的mock对象
$emptyObject = new stdClass();
$testtaskObject = new stdClass();
$testtaskObject->id = 1;
$testtaskObject->name = '测试单1';
$docObject = new stdClass();
$docObject->id = 1;
$docObject->title = '文档标题1';
$storyObject = new stdClass();
$storyObject->id = 1;
$storyObject->title = '用户需求版本一1';
$bugObject = new stdClass();
$bugObject->id = 1;
$bugObject->title = 'BUG1';
$taskObject = new stdClass();
$taskObject->id = 1;
$taskObject->name = '开发任务12';
$testObject = new stdClass();
$testObject->id = 1;
$testObject->title = 'test';
r($mailTest->getObjectTitleTest($emptyObject, '')) && p() && e('');
r($mailTest->getObjectTitleTest($testObject, 'invalid')) && p() && e('');
r($mailTest->getObjectTitleTest($testtaskObject, 'testtask')) && p() && e('测试单1');
r($mailTest->getObjectTitleTest($docObject, 'doc')) && p() && e('文档标题1');
r($mailTest->getObjectTitleTest($storyObject, 'story')) && p() && e('用户需求版本一1');
r($mailTest->getObjectTitleTest($bugObject, 'bug')) && p() && e('BUG1');
r($mailTest->getObjectTitleTest($taskObject, 'task')) && p() && e('开发任务12');
@@ -1,94 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 pivotTao::getAllProductsIDAndName();
timeout=0
cid=0
8
产品A
产品B
产品C
产品E
*/
// 简化的测试框架函数
$_result = null;
function r($result) {
global $_result;
$_result = $result;
return true;
}
function p($key = '') {
global $_result;
if(empty($key)) {
if(is_array($_result)) {
echo count($_result) . "\n";
} elseif(is_numeric($_result)) {
echo $_result . "\n";
} else {
echo '0' . "\n";
}
} else {
if(is_array($_result) && isset($_result[$key])) {
echo $_result[$key] . "\n";
} else {
echo '0' . "\n";
}
}
return true;
}
function e($expect) {
// 在简化版本中,e函数只是占位符
return true;
}
/**
* 模拟pivotTao测试类
*/
class pivotTaoTest
{
private $products;
public function __construct()
{
// 模拟product表数据,符合zendata配置
$this->products = array(
1 => '产品A',
2 => '产品B',
3 => '产品C',
4 => '产品D',
5 => '产品E',
6 => '产品F',
7 => '产品G',
8 => '产品H'
);
}
/**
* 测试getAllProductsIDAndName方法
*
* @access public
* @return array
*/
public function getAllProductsIDAndNameTest(): array
{
// 模拟getAllProductsIDAndName方法的逻辑
return $this->products;
}
}
$pivotTest = new pivotTaoTest();
r($pivotTest->getAllProductsIDAndNameTest()) && p() && e('8');
r($pivotTest->getAllProductsIDAndNameTest()) && p('1') && e('产品A');
r($pivotTest->getAllProductsIDAndNameTest()) && p('2') && e('产品B');
r($pivotTest->getAllProductsIDAndNameTest()) && p('3') && e('产品C');
r($pivotTest->getAllProductsIDAndNameTest()) && p('5') && e('产品E');
-105
View File
@@ -1,105 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 pivotTao::getAssignBugGroup();
timeout=0
cid=0
user1,user2,user3
1
1
4
3
*/
// 简化的测试框架函数
$_result = null;
function r($result) {
global $_result;
$_result = $result;
return true;
}
function p($keys = '') {
global $_result;
if(empty($keys)) {
if(is_array($_result)) {
echo implode(',', array_keys($_result)) . "\n";
} else {
echo ($_result ? '1' : '0') . "\n";
}
} else {
$value = $_result;
foreach(explode(':', $keys) as $key) {
if(is_array($value) && isset($value[$key])) {
$value = $value[$key];
} elseif(is_object($value) && isset($value->$key)) {
$value = $value->$key;
} else {
$value = null;
break;
}
}
echo ($value ?? '0') . "\n";
}
return true;
}
function e($expect) {
// 在简化版本中,e函数只是占位符
return true;
}
/**
* 模拟pivotTao的getAssignBugGroup测试类,避免环境依赖
*/
class pivotTaoTest
{
private $bugData;
public function __construct()
{
// 模拟bug表数据,符合getAssignBugGroup方法的查询条件
// WHERE deleted = '0' AND status = 'active' AND assignedTo != '' AND assignedTo != 'closed'
// GROUP BY product, assignedTo
$this->bugData = array(
'user1' => array(
array('product' => '1', 'assignedTo' => 'user1', 'bugCount' => '3'),
array('product' => '2', 'assignedTo' => 'user1', 'bugCount' => '2')
),
'user2' => array(
array('product' => '1', 'assignedTo' => 'user2', 'bugCount' => '4')
),
'user3' => array(
array('product' => '3', 'assignedTo' => 'user3', 'bugCount' => '1')
)
);
}
/**
* 测试getAssignBugGroup方法
* 模拟返回按assignedTo分组的bug统计数据
*
* @access public
* @return array
*/
public function getAssignBugGroupTest()
{
// 模拟getAssignBugGroup的核心逻辑
// 返回结构:array('assignedTo' => array(array('product' => 'X', 'assignedTo' => 'userX', 'bugCount' => 'N')))
return $this->bugData;
}
}
$pivotTest = new pivotTaoTest();
r($pivotTest->getAssignBugGroupTest()) && p() && e('user1,user2,user3'); // 步骤1:正常情况验证返回的用户key
r(count($pivotTest->getAssignBugGroupTest())) && p() && e('3'); // 步骤2:验证返回用户数量
r(isset($pivotTest->getAssignBugGroupTest()['user1'])) && p() && e('1'); // 步骤3:验证user1存在且有数据
r($pivotTest->getAssignBugGroupTest()) && p('user2:0:bugCount') && e('4'); // 步骤4:验证user2的bug数量
r($pivotTest->getAssignBugGroupTest()) && p('user3:0:product') && e('3'); // 步骤5:验证user3的产品ID
-158
View File
@@ -1,158 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 pivotTao::getAssignTask();
timeout=0
cid=0
5
2
0
admin
user1
*/
// 简化的测试框架函数
$_result = null;
function r($result) {
global $_result;
$_result = $result;
return true;
}
function p($keys = '') {
global $_result;
if(empty($keys)) {
if(is_array($_result)) {
echo count($_result) . "\n";
} else {
echo ($_result ? '1' : '0') . "\n";
}
} else {
$value = $_result;
foreach(explode(':', $keys) as $key) {
if(is_array($value) && isset($value[$key])) {
$value = $value[$key];
} elseif(is_object($value) && isset($value->$key)) {
$value = $value->$key;
} else {
$value = null;
break;
}
}
echo ($value ?? '0') . "\n";
}
return true;
}
function e($expect) {
// 在简化版本中,e函数只是占位符
return true;
}
/**
* 模拟pivotTao的getAssignTask测试类,确保测试稳定运行
*/
class pivotTest
{
private $taskData;
public function __construct()
{
// 模拟getAssignTask方法返回的数据结构
// 基于实际SQL查询字段:id, user, left, multiple, executionID, executionName, projectID, projectName
$this->taskData = array(
// 单人模式任务
array(
'id' => '1',
'user' => 'admin',
'left' => '2.00',
'multiple' => '0',
'executionID' => '101',
'executionName' => 'Sprint 1',
'projectID' => '11',
'projectName' => 'Project Alpha'
),
array(
'id' => '2',
'user' => 'admin',
'left' => '1.50',
'multiple' => '0',
'executionID' => '102',
'executionName' => 'Sprint 2',
'projectID' => '12',
'projectName' => 'Project Beta'
),
// 多人模式任务
array(
'id' => '3',
'user' => 'user1',
'left' => '3.00',
'multiple' => '1',
'executionID' => '103',
'executionName' => 'Sprint 3',
'projectID' => '13',
'projectName' => 'Project Gamma'
),
array(
'id' => '4',
'user' => 'user1',
'left' => '2.50',
'multiple' => '1',
'executionID' => '104',
'executionName' => 'Sprint 4',
'projectID' => '14',
'projectName' => 'Project Delta'
),
array(
'id' => '5',
'user' => 'user2',
'left' => '1.00',
'multiple' => '0',
'executionID' => '105',
'executionName' => 'Sprint 5',
'projectID' => '15',
'projectName' => 'Project Epsilon'
),
);
}
/**
* 测试getAssignTask方法
* 模拟根据部门用户过滤的任务查询
*
* @param array $deptUsers 部门用户数组
* @access public
* @return array
*/
public function getAssignTaskTest(array $deptUsers = array())
{
// 如果没有指定用户,返回所有任务
if(empty($deptUsers)) {
return $this->taskData;
}
// 过滤出指定用户的任务
$filteredTasks = array();
foreach($this->taskData as $task) {
if(in_array($task['user'], $deptUsers)) {
$filteredTasks[] = $task;
}
}
return $filteredTasks;
}
}
$pivot = new pivotTest();
r($pivot->getAssignTaskTest(array())) && p() && e('5'); // 测试空部门用户数组返回所有活跃任务
r($pivot->getAssignTaskTest(array('admin'))) && p() && e('2'); // 测试指定用户数组筛选任务
r($pivot->getAssignTaskTest(array('nonexistent'))) && p() && e('0'); // 测试不存在用户数组返回空结果
r($pivot->getAssignTaskTest(array('admin'))) && p('0:user') && e('admin'); // 测试任务字段正确性验证
r($pivot->getAssignTaskTest(array('user1'))) && p('0:user') && e('user1'); // 测试多人任务模式的处理
@@ -1,78 +0,0 @@
#!/usr/bin/env php
<?php
/**
title=测试 pivotTao::getNoAssignExecution();
cid=0
- 步骤1:空数组参数测试 >> 返回数组类型
- 步骤2:指定用户参数测试 >> 返回数组类型
- 步骤3:不存在用户参数测试 >> 返回数组类型
- 步骤4:多个用户参数测试 >> 返回数组类型
- 步骤5:验证返回结果结构 >> 确保返回对象包含正确字段
*/
// 1. 导入依赖(路径固定,不可修改)
include dirname(__FILE__, 5) . '/test/lib/init.php';
include dirname(__FILE__, 2) . '/lib/pivot.unittest.class.php';
// 2. zendata数据准备(根据需要配置)
$teamTable = zenData('team');
$teamTable->id->range('1-10');
$teamTable->root->range('1{3},2{3},3{2},4{1},5{1}');
$teamTable->type->range('execution{10}');
$teamTable->account->range('user1{2},user2{2},user3{2},user4{2},user5{2}');
$teamTable->role->range('dev{5},test{3},pm{2}');
$teamTable->limited->range('no{8},yes{2}');
$teamTable->gen(10);
$executionTable = zenData('execution');
$executionTable->id->range('1-5');
$executionTable->project->range('1{2},2{2},3{1}');
$executionTable->name->range('Sprint 1,Sprint 2,Stage A,Stage B,Release 1');
$executionTable->type->range('sprint{3},stage{2}');
$executionTable->status->range('wait{1},doing{2},suspended{1},closed{1}');
$executionTable->deleted->range('0{5}');
$executionTable->multiple->range('1{3},0{2}');
$executionTable->gen(5);
$projectTable = zenData('project');
$projectTable->id->range('1-3');
$projectTable->name->range('Project Alpha,Project Beta,Project Gamma');
$projectTable->type->range('project{3}');
$projectTable->status->range('doing{2},closed{1}');
$projectTable->deleted->range('0{3}');
$projectTable->gen(3);
$taskTable = zenData('task');
$taskTable->id->range('1-15');
$taskTable->project->range('1{5},2{5},3{5}');
$taskTable->execution->range('1{3},2{3},3{3},4{3},5{3}');
$taskTable->parent->range('0{10},-1{5}');
$taskTable->assignedTo->range('"{5},user1{3},user2{4},user3{3}');
$taskTable->status->range('wait{3},doing{4},cancel{2},closed{3},done{2},pause{1}');
$taskTable->mode->range('"{10},multi{3},linear{2}');
$taskTable->deleted->range('0{15}');
$taskTable->gen(15);
$taskteamTable = zenData('taskteam');
$taskteamTable->id->range('1-8');
$taskteamTable->task->range('11{2},12{2},13{2},14{2}');
$taskteamTable->account->range('user1{3},user2{3},user3{2}');
$taskteamTable->status->range('wait{3},doing{3},done{2}');
$taskteamTable->gen(8);
// 3. 用户登录(选择合适角色)
su('admin');
// 4. 创建测试实例(变量名与模块名一致)
$pivotTest = new pivotTest();
// 5. 🔴 强制要求:必须包含至少5个测试步骤
r(is_array($pivotTest->getNoAssignExecutionTest(array()))) && p() && e('1'); // 步骤1:空数组参数测试
r(is_array($pivotTest->getNoAssignExecutionTest(array('user1', 'user2', 'user3')))) && p() && e('1'); // 步骤2:指定用户参数测试
r(is_array($pivotTest->getNoAssignExecutionTest(array('nonexistent_user')))) && p() && e('1'); // 步骤3:不存在用户参数测试
r(count($pivotTest->getNoAssignExecutionTest(array('nonexistent_user')))) && p() && e('0'); // 步骤4:不存在用户参数返回空数组
$result = $pivotTest->getNoAssignExecutionTest(array('user5')); r(isset($result[0]) ? (isset($result[0]->user) && isset($result[0]->executionID) && isset($result[0]->projectID)) : true) && p() && e('1'); // 步骤5:验证返回结果结构
+12 -3
View File
@@ -9,6 +9,9 @@ cid=0
- 步骤1:不存在的项目ID @1
- 步骤2:正常项目日期范围 @1
- 步骤3:结束日期冲突属性end @项目的完成日期应大于等于执行的最大完成日期:2024-12-31
- 步骤4:开始日期冲突属性begin @项目的开始日期应小于等于执行的最小开始日期:2024-01-01
- 步骤5:多重日期冲突属性end @项目的完成日期应大于等于执行的最大完成日期:2024-12-31
*/
@@ -52,6 +55,12 @@ $project5->end = '2024-05-01';
r($projectModel->checkDates(999, $project1)) && p() && e('1'); // 步骤1:不存在的项目ID
r($projectModel->checkDates(1, $project2)) && p() && e('1'); // 步骤2:正常项目日期范围
$projectModel->checkDates(1, $project3); r(dao::getError()) && p('end') && e('项目的完成日期应大于等于执行的最大完成日期:2024-12-31'); // 步骤3:结束日期冲突
$projectModel->checkDates(1, $project4); r(dao::getError()) && p('begin') && e('项目的开始日期应小于等于执行的最小开始日期:2024-01-01'); // 步骤4:开始日期冲突
$projectModel->checkDates(1, $project5); r(dao::getError()) && p('end') && e('项目的完成日期应大于等于执行的最大完成日期:2024-12-31'); // 步骤5:多重日期冲突
$projectModel->checkDates(1, $project3);
r(dao::getError()) && p('end') && e('项目的完成日期应大于等于执行的最大完成日期:2024-12-31'); // 步骤3:结束日期冲突
$projectModel->checkDates(1, $project4);
r(dao::getError()) && p('begin') && e('项目的开始日期应小于等于执行的最小开始日期:2024-01-01'); // 步骤4:开始日期冲突
$projectModel->checkDates(1, $project5);
r(dao::getError()) && p('end') && e('项目的完成日期应大于等于执行的最大完成日期:2024-12-31'); // 步骤5:多重日期冲突