Merge branch 'master' into 'sprint/tianshujie_bug16527'

# Conflicts:
#   module/testcase/control.php
#   module/testcase/view/batchedit.html.php
This commit is contained in:
王怡栋
2022-04-12 06:57:23 +00:00
46 changed files with 584 additions and 75 deletions
+3
View File
@@ -23,6 +23,9 @@ class testcasesEntry extends entry
if(empty($productID)) $productID = $this->param('product', 0);
if(empty($productID)) return $this->sendError(400, 'Need product id.');
$this->app->cookie->caseModule = 0;
$this->app->cookie->caseSuite = 0;
$type = 'all';
$param = 0;
$moduleID = $this->param('module', 0);
+1
View File
@@ -370,6 +370,7 @@ $config->objectTables['sonarqube'] = TABLE_PIPELINE;
$config->objectTables['gitlab'] = TABLE_PIPELINE;
$config->objectTables['jebkins'] = TABLE_PIPELINE;
$config->objectTables['stage'] = TABLE_STAGE;
$config->objectTables['apistruct'] = TABLE_APISTRUCT;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme', 'visions');
+5
View File
@@ -59,6 +59,11 @@ class control extends baseControl
{
foreach($exportFields as $field) $this->config->{$this->moduleName}->list->exportFields .= ",{$field->field}";
}
foreach($exportFields as $flowField => $exportField)
{
if(!isset($this->lang->{$this->moduleName}->$flowField)) $this->lang->{$this->moduleName}->$flowField = $exportField->name;
}
}
}
+2 -1
View File
@@ -43,6 +43,7 @@ $config->action->objectNameFields['kanbancard'] = 'name';
$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->objectNameFields['gitlab'] = 'name';
$config->action->objectNameFields['stage'] = 'name';
$config->action->objectNameFields['apistruct'] = 'name';
$config->action->commonImgSize = 870;
@@ -58,4 +59,4 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,';
-4
View File
@@ -76,10 +76,6 @@
{
echo $action->objectName;
}
elseif($action->objectType == 'program')
{
echo $action->objectName;
}
else
{
$tab = '';
+1 -2
View File
@@ -300,9 +300,8 @@ class api extends control
}
else
{
$this->api->deleteStruct($structID);
$this->api->delete(TABLE_APISTRUCT, $structID);
if(dao::isError()) return $this->sendError(dao::getError());
$this->action->create('apistruct', $structID, 'Deleted');
return print(js::locate(inlink('struct', "libID=$libID"), 'parent'));
}
}
-15
View File
@@ -173,21 +173,6 @@ class apiModel extends model
return common::createChanges($old, $data);
}
/**
* Delete a struct.
*
* @param int $id
* @access public
* @return void
*/
public function deleteStruct($id)
{
$this->dao->update(TABLE_APISTRUCT)
->set('deleted')->eq(1)
->where('id')->eq($id)
->exec();
}
/**
* Update an api doc.
*
+6
View File
@@ -19,6 +19,11 @@
<h2><?php echo $lang->api->managePublish;?></h2>
</div>
</div>
<?php if(empty($releases)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
</div>
<?php else:?>
<form class='main-table table-user' data-ride='table' method='post' data-checkable='false' id='userListForm'>
<table class='table has-sort-head' id='userList'>
<thead>
@@ -48,6 +53,7 @@
</tbody>
</table>
</form>
<?php endif;?>
</div>
</div>
<script>
+2
View File
@@ -101,3 +101,5 @@ ol, ul {margin-bottom: 0}
.tree li>.list-toggle {left: -4px; top: 0;}
.fullscreen-close {top: 8px !important;}
#subHeader .list-group>a.selected {color: #e9f2fb !important; background-color: #0c64eb !important;}
+6
View File
@@ -223,13 +223,19 @@ class docModel extends model
}
/**
* Update api lib.
*
* @param int $id
* @param stdClass $oldDoc
* @param array $data
* @access public
* @return array|int
*/
public function updateApiLib($id, $oldDoc, $data)
{
/* Replace doc library name. */
$this->lang->doclib->name = $this->lang->doclib->apiLibName;
$data->type = static::DOC_TYPE_API;
$this->dao->update(TABLE_DOCLIB)->data($data)->autoCheck()
->batchCheck($this->config->api->editlib->requiredFields, 'notempty')
+71 -1
View File
@@ -2,7 +2,22 @@ $(function()
{
$('#execution_chosen').click(function()
{
if(systemMode == 'new') $('#execution_chosen ul li:first').append(' <label class="label">' + projectCommon + '</label>');
if(systemMode == 'new')
{
$('#execution_chosen ul li').each(function(index)
{
if(index == 0)
{
var projectName = subString($(this).text(), 56);
$(this).text(projectName);
$(this).append(' <label class="label">' + projectCommon + '</label>');
}
else
{
$(this).prepend('&nbsp;&nbsp;&nbsp;');
}
})
}
})
})
@@ -21,6 +36,13 @@ function setRole(account, roleID)
roleOBJ.val(role) // set the role.
}
/**
* Add item.
*
* @param object $obj
* @access public
* @return void
*/
function addItem(obj)
{
var item = $('#addItem').html().replace(/%i%/g, itemIndex);
@@ -40,12 +62,26 @@ function addItem(obj)
itemIndex ++;
}
/**
* Delete item.
*
* @param object $obj
* @access public
* @return void
*/
function deleteItem(obj)
{
if($('#teamForm .table tbody').children().length < 2) return false;
$(obj).closest('tr').remove();
}
/**
* Set dept users.
*
* @param object $obj
* @access public
* @return void
*/
function setDeptUsers(obj)
{
dept = $(obj).val(); // Get dept ID.
@@ -53,6 +89,13 @@ function setDeptUsers(obj)
location.href=link;
}
/**
* Chose team to copy.
*
* @param object $obj
* @access public
* @return void
*/
function choseTeam2Copy(obj)
{
team = $(obj).val();
@@ -60,3 +103,30 @@ function choseTeam2Copy(obj)
link = createLink('execution', 'manageMembers', 'executionID=' + executionID + '&team2Import=' + team + '&dept=' + dept);
location.href=link;
}
/**
* Cut a string of letters and characters with the same length.
*
* @param string $title
* @param int $stringLength
* @access public
* @return string
*/
function subString(title, stringLength)
{
if(title.replace(/[\u4e00-\u9fa5]/g, "**").length > stringLength)
{
var length = 0;
for(var i = 0; i < title.length; i ++)
{
length += title.charCodeAt(i) > 255 ? 2 : 1;
if(length > stringLength)
{
title = title.substring(0, i) + '...';
break;
}
}
}
return title;
}
+1
View File
@@ -75,6 +75,7 @@ $lang->execution->storyTitle = "Story Name";
$lang->execution->all = "All {$lang->executionCommon}s";
$lang->execution->undone = 'Unfinished ';
$lang->execution->unclosed = 'Unclosed';
$lang->execution->closedExecution = 'Closed Execution';
$lang->execution->typeDesc = "OPS {$lang->executionCommon} has no {$lang->SRCommon}, Bug, Build, or Test features.";
$lang->execution->mine = 'Mine: ';
$lang->execution->involved = 'Mine';
+1
View File
@@ -75,6 +75,7 @@ $lang->execution->storyTitle = "{$lang->SRCommon}名称";
$lang->execution->all = '所有';
$lang->execution->undone = '未完成';
$lang->execution->unclosed = '未关闭';
$lang->execution->closedExecution = '已关闭的执行';
$lang->execution->typeDesc = "运维{$lang->executionCommon}没有{$lang->SRCommon}、bug、版本、测试功能。";
$lang->execution->mine = '我负责:';
$lang->execution->involved = '我参与';
+25 -1
View File
@@ -22,6 +22,9 @@
#swapper li > a {margin-top: 4px; margin-bottom: 4px;}
#swapper li {padding-top: 0; padding-bottom: 0;}
#swapper .tree li>.list-toggle {top: -1px;}
#closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;}
#gray-line {height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;}
</style>
<?php
$executionCounts = array();
@@ -130,6 +133,8 @@ $closedExecutionsHtml .= '</ul>';
<a class='pull-right toggle-right-col not-list-item'><?php echo $lang->execution->doneExecutions;?><i class='icon icon-angle-right'></i></a>
</div>
</div>
<div id="gray-line"></div>
<div id="closed" hidden><?php echo $lang->execution->closedExecution?></div>
<div class="table-col col-right executionTree">
<div class='list-group executions'><?php echo $closedExecutionsHtml;?></div>
</div>
@@ -165,6 +170,25 @@ $(function()
$('li.has-list div.hide-in-search').removeClass('hidden');
$('.nav-tabs li.active').find('span').show();
}
})
if($('.form-control.search-input').val().length > 0)
{
$('#closed').attr("hidden", false);
$('#gray-line').attr("hidden", false);
}
else
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
$('#swapper #dropMenu').on('onSearchComplete', function(event, value)
{
if($('.list-group.executions').height() == 0)
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
})
</script>
+21
View File
@@ -654,6 +654,27 @@
$(window).on('resize', refreshMoreMenu);
refreshMoreMenu();
setTimeout(refreshMoreMenu, 500);
/* Fix bug #21331. */
var vibibleState = '';
var visibleChange = '';
if(typeof document.visibilityState != 'undefined')
{
visibleChange = 'visibilitychange';
  vibibleState = 'visibilityState';
}
else if(typeof document.webkitVisibilityState != 'undefined')
{
visibleChange = 'webkitvisibilitychange';
  vibibleState = 'webkitVisibilityState';
}
if(visibleChange)
{
document.addEventListener(visibleChange, function()
{
if(document[vibibleState] == 'visible') showTab($('#bars>li.active').data('app'));
});
}
});
}());
-2
View File
@@ -38,5 +38,3 @@ a.removeModule:hover {color: red;}
#batchUnlinkStoryTip .table td {border-bottom: 0px;}
#batchUnlinkStoryTip .table th:first-child {width: 460px;}
#mainMenu .dropdown-menu>li>a>.icon {top: 4px;}
#myProduct {border-bottom: 1px solid #ddd;}
+1
View File
@@ -23,6 +23,7 @@ $lang->product->select = "Select {$lang->productCommon}";
$lang->product->mine = 'Mine';
$lang->product->other = 'Others';
$lang->product->closed = 'Closed';
$lang->product->closedProduct = 'Closed Product';
$lang->product->updateOrder = 'Order';
$lang->product->all = "{$lang->productCommon} List";
$lang->product->manageLine = "Manage {$lang->productCommon} Line";
+1
View File
@@ -23,6 +23,7 @@ $lang->product->select = "请选择{$lang->productCommon}";
$lang->product->mine = '我负责';
$lang->product->other = '其他';
$lang->product->closed = '已关闭';
$lang->product->closedProduct = '已关闭的产品';
$lang->product->updateOrder = '排序';
$lang->product->all = "所有{$lang->productCommon}";
$lang->product->manageLine = "维护{$lang->productCommon}线";
+42 -1
View File
@@ -1801,7 +1801,11 @@ class productModel extends model
->andWhere('status')->eq('normal')
->fetchGroup('product', 'id');
return array('programList' => $programList, 'productList' => $productList, 'planList' => $planList, 'projectList' => $projectList, 'executionList' => $executionList, 'projectProduct' => $projectProduct, 'projectLatestExecutions' => $projectLatestExecutions, 'hourList' => $hourList, 'releaseList' => $releaseList);
/* Convert predefined HTML entities to characters. */
$statsData = array('programList' => $programList, 'productList' => $productList, 'planList' => $planList, 'projectList' => $projectList, 'executionList' => $executionList, 'projectProduct' => $projectProduct, 'projectLatestExecutions' => $projectLatestExecutions, 'hourList' => $hourList, 'releaseList' => $releaseList);
$statsData = $this->covertHtmlSpecialChars($statsData);
return $statsData;
}
/**
@@ -2256,4 +2260,41 @@ class productModel extends model
$this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
}
}
/**
* Convert predefined HTML entities to characters
*
* @param array $statsData
* @return array
*/
public function covertHtmlSpecialChars($statsData)
{
if(empty($statsData)) return array();
foreach($statsData as $key => $data)
{
if($key == 'productList' || $key == 'projectList')
{
!empty($data) && array_map(function($item)
{
return $item->name = htmlspecialchars_decode($item->name, ENT_QUOTES);
},
$data);
}
if($key == 'planList')
{
foreach($data as $productID => $plan)
{
!empty($plan) && array_map(function($planItem)
{
return $planItem->title = htmlspecialchars_decode($planItem->title, ENT_QUOTES);
},
$plan);
}
}
}
return $statsData;
}
}
@@ -26,6 +26,8 @@
#swapper .tree li>.list-toggle {top: -1px;}
#subHeader .tree ul {display: block;}
#closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;}
#gray-line {height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;}
</style>
<?php
$productCounts = array();
@@ -135,6 +137,8 @@ $closedProductsHtml .= '</ul>';
<a class='pull-right toggle-right-col not-list-item'><?php echo $lang->product->closed?><i class='icon icon-angle-right'></i></a>
</div>
</div>
<div id="gray-line"></div>
<div id="closed" hidden><?php echo $lang->product->closedProduct?></div>
<div class="table-col col-right productTree">
<div class='list-group products'><?php echo $closedProductsHtml;?></div>
</div>
@@ -170,6 +174,16 @@ $(function()
$('li.has-list div.hide-in-search').removeClass('hidden');
$('.nav-tabs li.active').find('span').show();
}
if($('.form-control.search-input').val().length > 0)
{
$('#closed').attr("hidden", false);
$('#gray-line').attr("hidden", false);
}
else
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
$('#swapper #dropMenu').on('onSearchComplete', function(event, value)
@@ -184,6 +198,11 @@ $(function()
{
$("#navTabs a[href='#other']").tab('show');
}
if($('ul.tree-angles').height() == 0)
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
})
</script>
+7
View File
@@ -247,6 +247,7 @@ class programModel extends model
return $planVal->title = htmlspecialchars_decode($planVal->title, ENT_QUOTES);
},
$product->plans);
$product->name = htmlspecialchars_decode($product->name, ENT_QUOTES);
$product->releases = zget($releases, $product->id, array());
$projects = zget($projectGroup, $product->id, array());
@@ -265,6 +266,9 @@ class programModel extends model
$project->execution = $execution;
$project->hours['progress'] = zget($projectHours, $project->id, array());
/* Convert predefined HTML entities to characters. */
$project->name = htmlspecialchars_decode($project->name, ENT_QUOTES);
$product->projects[$status][] = $project;
}
}
@@ -1368,6 +1372,9 @@ class programModel extends model
$project->leftTasks = isset($leftTasks[$project->id]) ? $leftTasks[$project->id]->tasks : '—';
$project->teamMembers = isset($teamMembers[$project->id]) ? array_keys($teamMembers[$project->id]) : array();
/* Convert predefined HTML entities to characters. */
$project->name = htmlspecialchars_decode($project->name, ENT_QUOTES);
$stats[$key] = $project;
}
return $stats;
+1
View File
@@ -171,6 +171,7 @@ $lang->project->waitProjects = 'Waiting Projects';
$lang->project->doingProjects = 'Ongoing Projects';
$lang->project->doingExecutions = 'Ongoing Executions';
$lang->project->closedProjects = 'Closed Projects(The recent two projects)';
$lang->project->closedProject = 'Closed Projects';
$lang->project->noProgram = 'Independent Projects';
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
+1
View File
@@ -171,6 +171,7 @@ $lang->project->waitProjects = '未开始的项目';
$lang->project->doingProjects = '进行中的项目';
$lang->project->doingExecutions = '进行中的执行(最近1个)';
$lang->project->closedProjects = '已关闭的项目(最近2个)';
$lang->project->closedProject = '已关闭的项目';
$lang->project->noProgram = '无项目集归属项目';
$lang->project->laneColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#FFC20E', '#00A78E', '#7FBB00', '#424BAC', '#C0E9FF', '#EC2761');
+25 -1
View File
@@ -23,6 +23,9 @@
#swapper li > a {margin-top: 4px; margin-bottom: 4px;}
#swapper li {padding-top: 0; padding-bottom: 0;}
#swapper .tree li>.list-toggle {top: -1px;}
#closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;}
#gray-line {height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;}
</style>
<?php
$projectCounts = array();
@@ -134,6 +137,8 @@ $closedProjectsHtml .= '</ul>';
<a class='pull-right toggle-right-col not-list-item'><?php echo $lang->project->doneProjects?><i class='icon icon-angle-right'></i></a>
</div>
</div>
<div id="gray-line" hidden></div>
<div id="closed" hidden><?php echo $lang->project->closedProject?></div>
<div class="table-col col-right projectTree">
<div class='list-group projects'><?php echo $closedProjectsHtml;?></div>
</div>
@@ -169,6 +174,25 @@ $(function()
$('li.has-list div.hide-in-search').removeClass('hidden');
$('.nav-tabs li.active').find('span').show();
}
})
if($('.form-control.search-input').val().length > 0)
{
$('#closed').attr("hidden", false);
$('#gray-line').attr("hidden", false);
}
else
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
$('#swapper #dropMenu').on('onSearchComplete', function(event, value)
{
if($('.list-group.projects').height() == 0)
{
$('#closed').attr("hidden", true);
$('#gray-line').attr("hidden", true);
}
});
})
</script>
+2 -2
View File
@@ -360,7 +360,7 @@ class repo extends control
public function browse($repoID = 0, $branchID = '', $objectID = 0, $path = '', $revision = 'HEAD', $refresh = 0)
{
$repoID = $this->repo->saveState($repoID, $objectID);
if($branchID) $branchID = base64_decode(urldecode($branchID));
if($branchID) $branchID = base64_decode(helper::safe64Decode($branchID));
/* Get path and refresh. */
if($this->get->repoPath) $path = $this->get->repoPath;
@@ -909,7 +909,7 @@ class repo extends control
$this->view->repoID = $repoID;
$this->view->objectID = $objectID;
$this->view->branch = $branch;
$this->view->browseLink = $this->repo->createLink('browse', "repoID=" . ($this->app->tab == 'devops' ? $repoID : '') . "&branchID=" . base64_encode($branch) . "&objectID=$objectID", '', false);
$this->view->browseLink = $this->repo->createLink('browse', "repoID=" . ($this->app->tab == 'devops' ? $repoID : '') . "&branchID=" . helper::safe64Encode(base64_encode($branch)) . "&objectID=$objectID", '', false);
$this->display();
}
+1 -1
View File
@@ -31,7 +31,7 @@ css::import($jsRoot . 'misc/highlight/styles/github.css');
<div class="page-title">
<strong>
<?php
$base64BranchID = base64_encode($branchID);
$base64BranchID = helper::safe64Encode(base64_encode($branchID));
echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID"), $repo->name, '', "data-app='{$app->tab}'");
$paths = explode('/', $entry);
$fileName = array_pop($paths);
+3 -3
View File
@@ -31,7 +31,7 @@
foreach($branches as $id => $branchName)
{
$isSelected = $id == $branchID ? 'class="selected"' : '';
$base64BranchID = urlencode(base64_encode($id));
$base64BranchID = helper::safe64Encode(base64_encode($id));
echo "<li $isSelected>" . html::a($this->createLink('repo', 'browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID"), $branchName, '', "title='{$branchName}' class='text-ellipsis' data-app='{$app->tab}'") . "</li>";
}
?>
@@ -41,7 +41,7 @@
<div class="page-title">
<strong>
<?php
$base64BranchID = base64_encode($branchID);
$base64BranchID = helper::safe64Encode(base64_encode($branchID));
echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID"), $repo->name, '', "data-app='{$app->tab}'");
$paths= explode('/', $path);
$fileName = array_pop($paths);
@@ -58,7 +58,7 @@
</div>
<div class="btn-toolbar pull-right">
<span class='last-sync-time'><?php echo $lang->repo->notice->lastSyncTime . $cacheTime?></span>
<?php echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID&path=" . $this->repo->encodePath($path) . "&revision=$revision&refresh=1"), "<i class='icon icon-refresh'></i> " . $lang->refresh, '', "class='btn btn-primary' data-app={$app->tab}");?>
<?php echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=" . helper::safe64Encode($base64BranchID) . "&objectID=$objectID&path=" . $this->repo->encodePath($path) . "&revision=$revision&refresh=1"), "<i class='icon icon-refresh'></i> " . $lang->refresh, '', "class='btn btn-primary' data-app={$app->tab}");?>
<?php if($repo->SCM == 'Gitlab' and common::hasPriv('gitlab', 'createBranch')) echo html::a($this->createLink('gitlab', 'createBranch', "gitlabID={$repo->gitlab}&projectID={$repo->project}"), "<i class='icon icon-sm icon-plus'></i> " . $lang->gitlab->createBranch, '', "class='btn btn-primary'");?>
</div>
</div>
+1 -1
View File
@@ -32,7 +32,7 @@
$paths = explode('/', $entry);
$fileName = array_pop($paths);
$postPath = '';
$base64BranchID = base64_encode($branchID);
$base64BranchID = helper::safe64Encode(base64_encode($branchID));
foreach($paths as $pathName)
{
$postPath .= $pathName . '/';
+1 -1
View File
@@ -20,7 +20,7 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php if(!isonlybody()):?>
<?php $browseLink = $app->session->revisionList != false ? $app->session->revisionList : $this->repo->createLink('browse', "repoID={$repoID}&branchID=" . base64_encode($branchID) . "&objectID=$objectID{$preDir}");?>
<?php $browseLink = $app->session->revisionList != false ? $app->session->revisionList : $this->repo->createLink('browse', "repoID={$repoID}&branchID=" . helper::safe64Encode(base64_encode($branchID)) . "&objectID=$objectID{$preDir}");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i> " . $lang->goback, '', "class='btn btn-link'");?>
<div class="divider"></div>
<?php endif;?>
+1 -1
View File
@@ -25,7 +25,7 @@ $version = " <span class=\"label label-info\">$revisionName</span>";
<div class="page-title">
<strong>
<?php
$base64BranchID = base64_encode($branchID);
$base64BranchID = helper::safe64Ecode(base64_encode($branchID));
echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID"), $repo->name, '', "data-app='{$app->tab}'");
$paths= explode('/', $entry);
$fileName = array_pop($paths);
+1
View File
@@ -1100,6 +1100,7 @@ class testcase extends control
$this->view->forceNotReview = $this->testcase->forceNotReview();
$this->view->modulePairs = $modulePairs;
$this->view->testtasks = $testtasks;
$this->view->isLibCase = $type == 'lib' ? true : false;
$this->display();
}
+10
View File
@@ -77,6 +77,16 @@ function loadBranches(product, branch, caseID, oldBranch)
}
}
$(document).ready(function()
{
/* Set secondary menu highlighting. */
if(isLibCase)
{
$('#navbar li[data-id=caselib]').addClass('active');
$('#navbar li[data-id=testcase]').removeClass('active');
}
})
$(function()
{
removeDitto(); //Remove 'ditto' in first row.
+1
View File
@@ -15,6 +15,7 @@
<?php js::set('productID', $productID);?>
<?php js::set('testtasks', $testtasks);?>
<?php js::set('confirmUnlinkTesttask', $lang->testcase->confirmUnlinkTesttask);?>
<?php js::set('isLibCase', $isLibCase);?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->testcase->common . $lang->colon . $lang->testcase->batchEdit;?></h2>
+1 -1
View File
@@ -321,7 +321,7 @@ class tree extends control
}
else
{
$this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, $branch);
$this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, $module->branch);
}
if($type == 'doc') $this->view->libs = $this->loadModel('doc')->getLibs('all', $extra = 'withObject');
+1 -1
View File
@@ -59,7 +59,7 @@
<caption class='text-left text-muted'><?php echo $lang->user->accountInfo;?></caption>
<tr>
<th class='w-140px'><?php echo $lang->user->account;?></th>
<td class='w-p40'><?php echo html::input('account', $user->account, "class='form-control' disabled");?></td>
<td class='w-p40'><?php echo html::input('account', $user->account, "class='form-control' readonly");?></td>
<th class='w-130px'><?php echo $lang->user->email;?></th>
<td>
<?php echo html::input('email', $user->email, "class='form-control'");?>
+99 -34
View File
@@ -98,27 +98,36 @@ class programplanTest
return implode(',', $objects);
}
public function getDataForGanttTest($executionID, $productID, $baselineID = 0, $selectCustom = '', $returnJson = false)
/**
* Test get total percent.
*
* @param int $stageID
* @param bool $parent
* @access public
* @return int
*/
public function getTotalPercentTest($stageID, $parent = false)
{
$objects = $this->objectModel->getDataForGantt($executionID, $productID, $baselineID, $selectCustom, $returnJson);
$stage = $this->objectModel->getByID($stageID);
$int = $this->objectModel->getTotalPercent($stage, $parent);
if(dao::isError()) return dao::getError();
$objects = is_string($objects) ? json_decode($objects) : $objects;
return $objects;
return $int;
}
public function getTotalPercentTest($stage, $parent = false)
/**
* Test process plans.
*
* @param array $planIDList
* @access public
* @return array
*/
public function processPlansTest($planIDList)
{
$objects = $this->objectModel->getTotalPercent($stage, $parent = false);
$plans = $this->objectModel->getByList($planIDList);
if(dao::isError()) return dao::getError();
return $objects;
}
public function processPlansTest($plans)
{
$objects = $this->objectModel->processPlans($plans);
if(dao::isError()) return dao::getError();
@@ -126,13 +135,22 @@ class programplanTest
return $objects;
}
public function processPlanTest($plan)
/**
* Test process plan.
*
* @param int $planID
* @access public
* @return object
*/
public function processPlanTest($planID)
{
$objects = $this->objectModel->processPlan($plan);
$plan = $this->objectModel->getByID($planID);
$object = $this->objectModel->processPlan($plan);
if(dao::isError()) return dao::getError();
return $objects;
return $object;
}
/**
@@ -162,62 +180,109 @@ class programplanTest
public function createTest($param = array())
{
$_POST['planIDList'] = array('131', '221', '311', '401', '491', '581', '671');
global $tester;
$plans = $tester->dao->select('*')->from(TABLE_PROJECT)->where('id')->in($_POST['planIDList'])->fetchAll();
$_POST['names'] = array('阶段31', '阶段121', '阶段211', '阶段301', '阶段391', '阶段481', '阶段571', '', '', '', '', '');
$_POST['PM'] = array('', '', '', '', '', '', '', '', '', '', '', '');
$_POST['percents'] = array('0', '0', '0', '0', '0', '0', '0', '', '', '', '', '');
$_POST['attributes'] = array('request', 'request', 'request', 'request', 'request', 'request', 'request', 'request', 'request', 'request', 'request', 'request');
$_POST['acl'] = array('private', 'open', 'open', 'private', 'private', 'open', 'open', 'open', 'open', 'open', 'open', 'open');
$_POST['milestone'] = array('0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0');
$_POST['begin'] = array('2022-03-13', '2022-03-13', '2022-03-16', '2022-03-16', '2022-03-19', '2022-03-19', '2022-03-22', '', '', '', '', '');
$_POST['end'] = array('2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '', '', '', '', '');
$_POST['begin'] = (isset($param['begin']) and isset($param['end'])) ? array($plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, '', '', '', '') : array($plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, $plans[0]->begin, '', '', '', '', '');
$_POST['end'] = (isset($param['begin']) and isset($param['end'])) ? array($plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, '', '', '', '') : array($plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, $plans[0]->end, '', '', '', '', '');
$_POST['realBegan'] = array('', '', '', '', '', '', '', '', '', '', '', '');
$_POST['realEnd'] = array('', '', '', '', '', '', '', '', '', '', '', '');
foreach($param as $field => $value) $_POST[$field] = $value;
foreach($param as $field => $value)
{
if(count($param) == 1 or ($field != 'begin' and $field != 'end')) $_POST[$field] = $value;
}
$objects = $this->objectModel->create(41, 0, 0);
unset($_POST);
if(dao::isError()) return dao::getError();
if(dao::isError())
{
$error = dao::getError()['message'][0];
$error = strpos($error, '所属项目的') > 0 ? preg_replace('/\d{4}-\d{2}-\d{2}/', '', $error) : $error;
return $error;
}
return $objects;
$objects = $tester->dao->select('*')->from(TABLE_PROJECT)->where('parent')->eq($plans[0]->parent)->andWhere('type')->eq('stage')->fetchAll();
return count($objects);
}
/**
* Test set stage tree path.
*
* @param int $planID
* @access public
* @return object
*/
public function setTreePathTest($planID)
{
$objects = $this->objectModel->setTreePath($planID);
$this->objectModel->setTreePath($planID);
if(dao::isError()) return dao::getError();
return $objects;
$object = $this->objectModel->getByID($planID);
return $object;
}
public function updateTest($planID = 0, $projectID = 0)
/**
* updateTest
*
* @param int $planID
* @param int $projectID
* @param array $param
* @param string $index
* @access public
* @return array
*/
public function updateTest($planID, $projectID, $param = array(), $index = '')
{
$objects = $this->objectModel->update($planID = 0, $projectID = 0);
$plan = $this->objectModel->getByID($planID);
if(dao::isError()) return dao::getError();
$_POST['parent'] = $plan->parent;
$_POST['name'] = $plan->name;
$_POST['percent'] = $plan->percent;
$_POST['attribute'] = $plan->attribute;
$_POST['milestone'] = $plan->milestone;
$_POST['acl'] = $plan->acl;
$_POST['begin'] = $plan->begin;
$_POST['end'] = $plan->end;
$_POST['realBegan'] = $plan->realBegan;
$_POST['realEnd'] = $plan->realEnd;
return $objects;
}
foreach($param as $key => $value) $_POST[$key] = $value;
public function printCellTest($col, $plan, $users, $projectID)
{
$objects = $this->objectModel->printCell($col, $plan, $users, $projectID);
$objects = $this->objectModel->update($planID, $projectID);
if(dao::isError()) return dao::getError();
unset($_POST);
if(dao::isError()) return $index == 'end' ? preg_replace('/『\d{4}-\d{2}-\d{2}』/', '', dao::getError()[$index][0]) : dao::getError()[$index][0];
return $objects;
}
/**
* Test is create task.
*
* @param int $planID
* @access public
* @return int
*/
public function isCreateTaskTest($planID)
{
$objects = $this->objectModel->isCreateTask($planID);
$object = $this->objectModel->isCreateTask($planID);
if(dao::isError()) return dao::getError();
return $objects;
return $object ? 2 : 1;
}
/**
+1 -1
View File
@@ -22,7 +22,7 @@ fields:
- field: status
range: wait,doing
- field: percent
range: 0
range: 0{30},10{30},0{30}
- field: milestone
range: 0{30},1{10},0{10},1{10},0{30}
- field: auth
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->create();
cid=1
pid=1
*/
$percentNumber = array('percents' => array('a', '0', '0', '0', '0', '0', '0', '', '', '', '', ''));
$emptyBegin = array('begin' => array('', '2022-03-13', '2022-03-16', '2022-03-16', '2022-03-19', '2022-03-19', '2022-03-22', '', '', '', '', ''));
$checkBegin = array('begin' => array('a', '2022-03-13', '2022-03-16', '2022-03-16', '2022-03-19', '2022-03-19', '2022-03-22', '', '', '', '', ''));
$emptyEnd = array('end' => array('', '2022-04-30', '2022-05-18', '2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '', '', '', '', ''));
$checkEnd = array('end' => array('a', '2022-04-30', '2022-05-18', '2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '', '', '', '', ''));
$planFinishSmall = array('end' => array('2022-03-12', '2022-04-30', '2022-05-18', '2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '', '', '', '', ''));
$errorBegin = array('begin' => array('2022-01-01', '2022-03-13', '2022-03-16', '2022-03-16', '2022-03-19', '2022-03-19', '2022-03-22', '', '', '', '', ''));
$errorEnd = array('end' => array('2100-06-18', '2022-04-30', '2022-05-18', '2022-05-18', '2022-04-30', '2022-05-18', '2022-05-18', '', '', '', '', ''));
$percentOver = array('percents' => array('50', '51', '0', '0', '0', '0', '0', '', '', '', '', ''));
$names = array('阶段31', '阶段121', '阶段211', '阶段301', '阶段391', '阶段481', '阶段571', '新增的阶段', '', '', '', '');
$percents = array('0', '0', '0', '0', '0', '0', '0', '0', '', '', '', '');
$begin = array();
$end = array();
$create = array('names' => $names, 'percents' => $percents, 'begin' => $begin, 'end' => $end);
$programplan = new programplanTest();
r($programplan->createTest($percentNumber)) && p() && e('"工作量比例"必须为数字'); // 测试创建用例 工作量占比非数字
r($programplan->createTest($emptyBegin)) && p() && e('『计划开始』日期不能为空'); // 测试创建用例 计划开始为空
r($programplan->createTest($checkBegin)) && p() && e('『计划开始』应当为合法的日期'); // 测试创建用例 计划开始非日期
r($programplan->createTest($emptyEnd)) && p() && e('『计划完成』日期不能为空'); // 测试创建用例 计划完成为空
r($programplan->createTest($checkEnd)) && p() && e('『计划完成』应当为合法的日期'); // 测试创建用例 计划完成非日期
r($programplan->createTest($planFinishSmall)) && p() && e('"计划完成时间"必须大于"计划开始时间"'); // 测试创建用例 计划完成小于计划开始
r($programplan->createTest($errorBegin)) && p() && e("阶段的开始时间不能小于所属项目的开始时间"); // 测试创建用例 计划开始小于项目开始日期
r($programplan->createTest($errorEnd)) && p() && e("阶段的结束时间不能大于所属项目的结束时间"); // 测试创建用例 计划完成大于项目计划完成
r($programplan->createTest($percentOver)) && p() && e('工作量占比累计不应当超过100%'); // 测试创建用例 工作量占比之和大于100
r($programplan->createTest()) && p() && e('7'); // 测试正常更新阶段信息 获取阶段数量
r($programplan->createTest($create)) && p() && e('8'); // 测试正常创建一条阶段信息 获取阶段数量
system("./ztest init");
@@ -16,7 +16,7 @@ $productIDList = array(21, 32, 23, 34, 25);
$programplan = new programplanTest();
r($programplan->getMilestoneByProductTest($productIDList[0], $projectIDList[0])) && p() && e('阶段301,阶段481,阶段211,阶段391,阶段571'); // 测试获取产品21 项目41的里程碑
r($programplan->getMilestoneByProductTest($productIDList[0], $projectIDList[0])) && p() && e('阶段121,阶段301,阶段481,阶段31,阶段211,阶段391,阶段571'); // 测试获取产品21 项目41的里程碑
r($programplan->getMilestoneByProductTest($productIDList[1], $projectIDList[1])) && p() && e('0'); // 测试获取产品32 项目52的里程碑
r($programplan->getMilestoneByProductTest($productIDList[2], $projectIDList[2])) && p() && e('阶段123,阶段303,阶段483,阶段33,阶段213,阶段393,阶段573'); // 测试获取产品23 项目43的里程碑
r($programplan->getMilestoneByProductTest($productIDList[3], $projectIDList[3])) && p() && e('0'); // 测试获取产品34 项目54的里程碑
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->getPairs();
cid=1
pid=1
*/
$executionIDList = array(41, 42, 43, 44, 45);
$productIDList = array(21, 22, 23, 24, 25);
$programplan = new programplanTest();
r($programplan->getPairsTest($executionIDList[0], $productIDList[0])) && p() && e(',阶段31,阶段31/子阶段1,阶段121,阶段211,阶段301,阶段391,阶段481,阶段571'); // 测试获取执行41 产品21的计划键值对
r($programplan->getPairsTest($executionIDList[1], $productIDList[1])) && p() && e(',阶段32,阶段32/子阶段2,阶段122,阶段212,阶段302,阶段392,阶段482,阶段572'); // 测试获取执行42 产品22的计划键值对
r($programplan->getPairsTest($executionIDList[2], $productIDList[2])) && p() && e(',阶段33,阶段33/子阶段3,阶段123,阶段213,阶段303,阶段393,阶段483,阶段573'); // 测试获取执行43 产品23的计划键值对
r($programplan->getPairsTest($executionIDList[3], $productIDList[3])) && p() && e(',阶段34,阶段34/子阶段4,阶段124,阶段214,阶段304,阶段394,阶段484,阶段574'); // 测试获取执行44 产品24的计划键值对
r($programplan->getPairsTest($executionIDList[4], $productIDList[4])) && p() && e(',阶段35,阶段35/子阶段5,阶段125,阶段215,阶段305,阶段395,阶段485,阶段575'); // 测试获取执行45 产品25的计划键值对
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->getTotalPercent();
cid=1
pid=1
*/
$stageIDList = array(131, 132, 133, 134, 135);
$programplan = new programplanTest();
r($programplan->getTotalPercentTest($stageIDList[0])) && p() && e('60'); // 测试获取阶段131的总进度
r($programplan->getTotalPercentTest($stageIDList[0], true)) && p() && e('0'); // 测试获取阶段131是父阶段的总进度
r($programplan->getTotalPercentTest($stageIDList[1])) && p() && e('60'); // 测试获取阶段132的总进度
r($programplan->getTotalPercentTest($stageIDList[2])) && p() && e('60'); // 测试获取阶段133的总进度
r($programplan->getTotalPercentTest($stageIDList[3])) && p() && e('60'); // 测试获取阶段134的总进度
r($programplan->getTotalPercentTest($stageIDList[4])) && p() && e('60'); // 测试获取阶段135的总进度
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->isCreateTask();
cid=1
pid=1
*/
$stageIDList = array(131, 132, 133, 134, 135);
$programplan = new programplanTest();
r($programplan->isCreateTaskTest($stageIDList[0])) && p() && e('1'); // 测试阶段131下有没有任务
r($programplan->isCreateTaskTest($stageIDList[1])) && p() && e('1'); // 测试阶段132下有没有任务
r($programplan->isCreateTaskTest($stageIDList[2])) && p() && e('1'); // 测试阶段133下有没有任务
r($programplan->isCreateTaskTest($stageIDList[3])) && p() && e('1'); // 测试阶段134下有没有任务
r($programplan->isCreateTaskTest($stageIDList[4])) && p() && e('1'); // 测试阶段135下有没有任务
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->processPlan();
cid=1
pid=1
*/
$planIDList = array(131, 132, 133, 134, 135);
$programplan = new programplanTest();
r($programplan->processPlanTest($planIDList[0])) && p('id,name,productName') && e('131,阶段31,已关闭的正常产品21'); // 测试计算计划131
r($programplan->processPlanTest($planIDList[1])) && p('id,name,productName') && e('132,阶段32,已关闭的正常产品22'); // 测试计算计划132
r($programplan->processPlanTest($planIDList[2])) && p('id,name,productName') && e('133,阶段33,已关闭的正常产品23'); // 测试计算计划133
r($programplan->processPlanTest($planIDList[3])) && p('id,name,productName') && e('134,阶段34,已关闭的正常产品24'); // 测试计算计划134
r($programplan->processPlanTest($planIDList[4])) && p('id,name,productName') && e('135,阶段35,已关闭的正常产品25'); // 测试计算计划135
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->processPlans();
cid=1
pid=1
*/
$planIDList = array(array(11, 12), array(13, 14), array(15, 16, 17), array(18, 19, 20), array(21, 22, 23, 24));
$programplan = new programplanTest();
r($programplan->processPlansTest($planIDList[0])) && p('11:name,productName;12:name,productName') && e('项目1,正常产品1;项目2,正常产品2'); // 测试获取计划 11 12的信息
r($programplan->processPlansTest($planIDList[1])) && p('13:name,productName;14:name,productName') && e('项目3,正常产品3;项目4,正常产品4'); // 测试获取计划 13 14的信息
r($programplan->processPlansTest($planIDList[2])) && p('15:name,productName;16:name,productName;17:name,productName') && e('项目5,正常产品5;项目6,正常产品6;项目7,正常产品7'); // 测试获取计划 15 16 17的信息
r($programplan->processPlansTest($planIDList[3])) && p('18:name,productName;19:name,productName;20:name,productName') && e('项目8,正常产品8;项目9,正常产品9;项目10,正常产品10'); // 测试获取计划 18 19 20的信息
r($programplan->processPlansTest($planIDList[4])) && p('21:name,productName;22:name,productName;23:name,productName;24:name,productName') && e('项目11,正常产品1;项目12,正常产品2;项目13,正常产品3;项目14,正常产品4'); // 测试获取计划 21 22 23 24的信息
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->setTreePath();
cid=1
pid=1
*/
$planIDList = array(131, 132, 133, 134, 135);
$programplan = new programplanTest();
r($programplan->setTreePathTest($planIDList[0])) && p('name;path') && e('阶段31;,41,131,'); // 测试更新计划131的路径
r($programplan->setTreePathTest($planIDList[1])) && p('name;path') && e('阶段32;,42,132,'); // 测试更新计划132的路径
r($programplan->setTreePathTest($planIDList[2])) && p('name;path') && e('阶段33;,43,133,'); // 测试更新计划133的路径
r($programplan->setTreePathTest($planIDList[3])) && p('name;path') && e('阶段34;,44,134,'); // 测试更新计划134的路径
r($programplan->setTreePathTest($planIDList[4])) && p('name;path') && e('阶段35;,45,135,'); // 测试更新计划135的路径
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/programplan.class.php';
su('admin');
/**
title=测试 programplanModel->update();
cid=1
pid=1
*/
$planID = 131;
$projectID = 41;
$beginNotempty = array('begin' => '');
$endNotempty = array('end' => '');
$percentOver = array('percent' => 90);
$endLeBegin = array('end' => '2022-01-01');
$nameNotempty = array('name' => '');
$changeName = array('name' => '修改后的阶段');
$changePercent = array('percent' => '15');
$changeBegin = array('begin' => '2022-04-01');
$changeEnd = array('end' => '2022-04-30');
$programplan = new programplanTest();
//r($programplan->updateTest($planID, $projectID, $beginNotempty, 'begin')) && p() && e(''); // 测试修改plan的 begin 值 计划开始为空
//r($programplan->updateTest($planID, $projectID, $endNotempty, 'end')) && p() && e(''); // 测试修改plan的 end 值 计划完成为空
r($programplan->updateTest($planID, $projectID, $percentOver, 'percent')) && p() && e('工作量占比累计不应当超过100%'); // 测试修改plan的 percent 值 工作占比和超过100
r($programplan->updateTest($planID, $projectID, $endLeBegin, 'end')) && p() && e('『end』应当不小于。'); // 测试修改plan的 end 值 计划完成小于计划开始
r($programplan->updateTest($planID, $projectID, $nameNotempty, 'name')) && p() && e('『name』不能为空。'); // 测试修改plan的 name 值 名称为空
r($programplan->updateTest($planID, $projectID, $changeName)) && p('0:field,new') && e('name,修改后的阶段'); // 测试修改plan的 name 值
r($programplan->updateTest($planID, $projectID, $changePercent)) && p('0:field,new') && e('percent,15'); // 测试修改plan的 percent 值
r($programplan->updateTest($planID, $projectID, $changeBegin)) && p('0:field,new') && e('begin,2022-04-01'); // 测试修改plan的 begin 值
r($programplan->updateTest($planID, $projectID, $changeEnd)) && p('0:field,new') && e('end,2022-04-30'); // 测试修改plan的 end 值
system("./ztest init");