* finish task #2907,2910.

This commit is contained in:
wangyidong
2017-03-06 13:14:38 +08:00
parent 54f267e438
commit f1515951b0
19 changed files with 426 additions and 144 deletions
+40 -11
View File
@@ -192,6 +192,9 @@ class testcase extends control
$this->view->groupBy = $groupBy;
$this->view->groupByList = $groupByList;
$this->view->cases = $groupCases;
$this->view->suiteList = $this->loadModel('testsuite')->getSuites($productID);
$this->view->suiteID = 0;
$this->view->moduleID = 0;
$this->display();
}
@@ -343,6 +346,7 @@ class testcase extends control
{
$paddingCount = $this->config->testcase->defaultSteps - count($steps);
$step = new stdclass();
$step->type = 'item';
$step->desc = '';
$step->expect = '';
for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step;
@@ -596,6 +600,7 @@ class testcase extends control
if(empty($case->steps))
{
$step = new stdclass();
$step->type = 'item';
$step->desc = '';
$step->expect = '';
$case->steps[] = $step;
@@ -1103,7 +1108,7 @@ class testcase extends control
$relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
$relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
$relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
$relatedSteps = $this->dao->select('`case`, version, `desc`, expect')->from(TABLE_CASESTEP)->where('`case`')->in(@array_keys($cases))->orderBy('version desc,id')->fetchGroup('case');
$relatedSteps = $this->dao->select('parent,`case`,version,type,`desc`,expect')->from(TABLE_CASESTEP)->where('`case`')->in(@array_keys($cases))->orderBy('version desc,id')->fetchGroup('case');
$relatedModules = array('0' => '/') + $relatedModules;
foreach($cases as $case)
@@ -1112,14 +1117,25 @@ class testcase extends control
$case->stepExpect = '';
if(isset($relatedSteps[$case->id]))
{
$i = 1;
$i = $childId = 0;
foreach($relatedSteps[$case->id] as $step)
{
$stepId = 0;
if($step->type == 'group' or ($step->type == 'item' and $step->parent == 0))
{
$i++;
$childId = 0;
$stepId = $i;
}
else
{
$stepId = $i . '.' . $childId;
}
if($step->version != $case->version) continue;
$sign = (in_array($this->post->fileType, array('html', 'xml'))) ? '<br />' : "\n";
$case->stepDesc .= $i . ". " . htmlspecialchars_decode($step->desc) . $sign;
$case->stepExpect .= $i . ". " . htmlspecialchars_decode($step->expect) . $sign;
$i ++;
$case->stepDesc .= $stepId . ". " . htmlspecialchars_decode($step->desc) . $sign;
$case->stepExpect .= $stepId . ". " . htmlspecialchars_decode($step->expect) . $sign;
$childId ++;
}
}
@@ -1390,30 +1406,43 @@ class testcase extends control
{
$step = trim($step);
if(empty($step)) continue;
if(preg_match('/^([0-9]+)([.、]{1})/U', $step, $out))
if(preg_match('/^(([0-9]+)\.[0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$parent = $out[2];
$sign = $out[3];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'item';
$caseStep[$parent]['type'] = 'group';
}
elseif(preg_match('/^([0-9]+)([.、]{1})/U', $step, $out))
{
$num = $out[1];
$sign = $out[2];
$signbit = $sign == '.' ? 1 : 3;
$step = trim(substr($step, strpos($step, $sign) + $signbit));
if(!empty($step)) $caseStep[$num] = $step;
$step = trim(substr($step, strlen($num) + $signbit));
if(!empty($step)) $caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'item';
}
elseif(isset($num))
{
$caseStep[$num] .= "\n" . $step;
$caseStep[$num]['content'] .= "\n" . $step;
}
else
{
if($field == 'stepDesc')
{
$num = 1;
$caseStep[$num] = $step;
$caseStep[$num]['content'] = $step;
$caseStep[$num]['type'] = 'item';
}
if($field == 'stepExpect' and isset($stepData[$row]['desc']))
{
end($stepData[$row]['desc']);
$num = key($stepData[$row]['desc']);
$caseStep[$num] = $step;
$caseStep[$num]['content'] = $step;
}
}
}
+3 -3
View File
@@ -1,15 +1,15 @@
.table-form > tbody > tr > td .btn-group-vertical > .btn {margin-left: 0!important; padding: 2px 8px}
#steps .step-id {text-align: right}
#steps .step-child-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
#steps .step-item-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
#steps .checkbox-inline input[type="checkbox"] {top: -2px}
#steps .btn-group .btn {padding-left: 0; padding-right: 0; min-width: 30px;}
.step-actions {width: 100px;}
#steps .active td {transition: background-color .5s;}
#steps .step-group .step-steps {resize: none; max-height: 30px;}
#steps .step-group .step-expects {display: none;}
#steps .step-child .step-child-id {display: table-cell; min-width: 40px;}
#steps .step-child .step-id {color: transparent}
#steps .step-item .step-item-id {display: table-cell; min-width: 40px;}
#steps .step-item .step-id {color: transparent}
#steps .step-actions {width: 90px; text-align: center;}
#steps .btn-step-move {cursor: move}
+6 -3
View File
@@ -152,7 +152,7 @@ function initSteps(selector)
var stepID;
if(isGroup || !childId)
{
$step.removeClass('step-child');
$step.removeClass('step-item');
stepID = parentId++;
$step.find('.step-id').text(stepID);
if(isGroup) childId = 1;
@@ -160,9 +160,11 @@ function initSteps(selector)
else
{
stepID = (parentId - 1) + '.' + (childId++);
$step.addClass('step-child').find('.step-child-id').text(stepID);
$step.addClass('step-item').find('.step-item-id').text(stepID);
}
$step.find('.step-id-control').val(stepID);
$step.find('[name^="steps["]').attr('name', "steps[" +stepID + ']');
$step.find('[name^="stepType["]').attr('name', "stepType[" +stepID + ']');
$step.find('[name^="expects["]').attr('name', "expects[" +stepID + ']');
});
};
var initSortable = function()
@@ -210,6 +212,7 @@ function initSteps(selector)
refreshStepsID();
}).on('click', '.btn-step-delete', function()
{
if($('tbody#steps tr.step').size() == 1) return false;
$(this).closest('.step').remove();
refreshStepsID();
}).on('change', '.step-type', function()
+1
View File
@@ -13,6 +13,7 @@ $lang->testcase->id = '用例编号';
$lang->testcase->product = "所属{$lang->productCommon}";
$lang->testcase->module = '所属模块';
$lang->testcase->lib = "所属库";
$lang->testcase->branch = "分支/平台";
$lang->testcase->moduleAB = '模块';
$lang->testcase->story = '相关需求';
$lang->testcase->title = '用例标题';
+28 -7
View File
@@ -49,7 +49,7 @@ class testcaseModel extends model
->add('version', 1)
->add('fromBug', $bugID)
->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion((int)$this->post->story))
->remove('steps,expects,files,labels')
->remove('steps,expects,files,labels,stepType')
->setDefault('story', 0)
->join('stage', ',')
->get();
@@ -67,15 +67,20 @@ class testcaseModel extends model
{
$caseID = $this->dao->lastInsertID();
$this->loadModel('file')->saveUpload('testcase', $caseID);
$parentStepID = 0;
foreach($this->post->steps as $stepID => $stepDesc)
{
if(empty($stepDesc)) continue;
$isGroup = isset($_POST['stepType'][$stepID]);
$step = new stdClass();
$step->parent = $isGroup ? 0 : $parentStepID;
$step->case = $caseID;
$step->version = 1;
$step->type = $isGroup ? 'group' : 'item';
$step->desc = htmlspecialchars($stepDesc);
$step->expect = htmlspecialchars($this->post->expects[$stepID]);
$this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec();
if($isGroup) $parentStepID = $this->dao->lastInsertID();
}
return array('status' => 'created', 'id' => $caseID);
}
@@ -510,7 +515,7 @@ class testcaseModel extends model
->setIF($this->post->story != false and $this->post->story != $oldCase->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
->setDefault('story,branch', 0)
->join('stage', ',')
->remove('comment,steps,expects,files,labels')
->remove('comment,steps,expects,files,labels,stepType')
->get();
if($this->isForceReview() and $stepChanged) $case->status = 'wait';
$this->dao->update(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->edit->requiredFields, 'notempty')->where('id')->eq((int)$caseID)->exec();
@@ -518,15 +523,20 @@ class testcaseModel extends model
{
if($stepChanged)
{
$parentStepID = 0;
foreach($this->post->steps as $stepID => $stepDesc)
{
if(empty($stepDesc)) continue;
$isGroup = isset($_POST['stepType'][$stepID]);
$step = new stdclass();
$step->parent = $isGroup ? 0 : $parentStepID;
$step->case = $caseID;
$step->version = $version;
$step->type = $isGroup ? 'group' : 'item';
$step->desc = htmlspecialchars($stepDesc);
$step->expect = htmlspecialchars($this->post->expects[$stepID]);
$this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec();
if($isGroup) $parentStepID = $this->dao->lastInsertID();
}
}
@@ -931,13 +941,14 @@ class testcaseModel extends model
$steps = array();
if(isset($_POST['desc'][$key]))
{
foreach($this->post->desc[$key] as $id => $desc)
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc))continue;
$step = new stdclass();
$step->type = $data->stepType[$key][$id];
$step->desc = $desc;
$step->expect = trim($this->post->expect[$key][$id]);
$step->expect = trim($data->expect[$key][$id]);
$steps[] = $step;
}
@@ -974,16 +985,21 @@ class testcaseModel extends model
$this->dao->update(TABLE_CASE)->data($caseData)->where('id')->eq($caseID)->autoCheck()->exec();
if($stepChanged)
{
$parentStepID = 0;
foreach($steps as $id => $step)
{
$step = (array)$step;
if(empty($step['desc'])) continue;
$isGroup = $step['type'] == 'group';
$stepData = new stdclass();
$stepData->parent = $isGroup ? 0 : $parentStepID;
$stepData->case = $caseID;
$stepData->version = $version;
$stepData->type = $step['type'];
$stepData->desc = htmlspecialchars($step['desc']);
$stepData->expect = htmlspecialchars($step['expect']);
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($isGroup) $parentStepID = $this->dao->lastInsertID();
}
}
$oldCase->steps = $this->joinStep($oldStep);
@@ -1004,17 +1020,22 @@ class testcaseModel extends model
if(!dao::isError())
{
$caseID = $this->dao->lastInsertID();
foreach($this->post->desc[$key] as $id => $desc)
$caseID = $this->dao->lastInsertID();
$parentStepID = 0;
foreach($data->desc[$key] as $id => $desc)
{
$desc = trim($desc);
if(empty($desc)) continue;
$isGroup = $data->stepType[$key][$id] == 'group';
$stepData = new stdclass();
$stepData->parent = $isGroup ? 0 : $parentStepID;
$stepData->case = $caseID;
$stepData->version = 1;
$stepData->type = $isGroup ? 'group' : 'item';
$stepData->desc = htmlspecialchars($desc);
$stepData->expect = htmlspecialchars($this->post->expect[$key][$id]);
$stepData->expect = htmlspecialchars($data->expect[$key][$id]);
$this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec();
if($isGroup) $parentStepID = $this->dao->lastInsertID();
}
$this->action->create('case', $caseID, 'Opened');
}
+1 -1
View File
@@ -111,7 +111,7 @@
?>
</ul>
</div>
<?php common::printIcon('testcase', 'report', "productID=$productID&browseType=$browseType&branchID=$branch&moduleID=$moduleID"); ?>
<?php if(!($this->moduleName == 'story' and $this->methodName == 'zerocase')) common::printIcon('testcase', 'report', "productID=$productID&browseType=$browseType&branchID=$branch&moduleID=$moduleID"); ?>
</div>
<div class='btn-group'>
<div class='btn-group' id='createActionMenu'>
+7 -11
View File
@@ -140,10 +140,10 @@
</thead>
<tbody id='steps' class='sortable' data-group-name='<?php echo $lang->testcase->groupName ?>'>
<tr class='template step' id='stepTemplate'>
<td class='step-id'><input type='hidden' name='stepID[]' class='step-id-control'></td>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-child-id'></span>
<span class='input-group-addon step-item-id'></span>
<textarea rows='1' class='form-control autosize step-steps' name='steps[]'></textarea>
<span class="input-group-addon">
<label class="checkbox-inline">
@@ -152,9 +152,7 @@
</span>
</div>
</td>
<td>
<textarea rows='1' class='form-control autosize step-expects' name='expects[]'></textarea>
</td>
<td><textarea rows='1' class='form-control autosize step-expects' name='expects[]'></textarea></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
@@ -165,21 +163,19 @@
</tr>
<?php foreach($steps as $stepID => $step):?>
<tr class='step'>
<td class='step-id'><input type='hidden' name='stepID[]' class='step-id-control'></td>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-child-id'></span>
<span class='input-group-addon step-item-id'></span>
<?php echo html::textarea('steps[]', $step->desc, "rows='1' class='form-control autosize step-steps'") ?>
<span class="input-group-addon">
<label class="checkbox-inline">
<input type='checkbox' name='stepType[]' value='parent' class='step-type'> <?php echo $lang->testcase->group ?>
<input type='checkbox' name='stepType[]' value='parent' class='step-type' <?php if($step->type == 'group') echo 'checked'?>> <?php echo $lang->testcase->group ?>
</label>
</span>
</div>
</td>
<td>
<?php echo html::textarea('expects[]', $step->expect, "rows='1' class='form-control autosize step-expects'") ?>
</td>
<td><?php echo html::textarea('expects[]', $step->expect, "rows='1' class='form-control autosize step-expects'") ?></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
+7 -11
View File
@@ -53,10 +53,10 @@
</thead>
<tbody id='steps' class='sortable' data-group-name='<?php echo $lang->testcase->groupName ?>'>
<tr class='template step' id='stepTemplate'>
<td class='step-id'><input type='hidden' name='stepID[]' class='step-id-control'></td>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-child-id'></span>
<span class='input-group-addon step-item-id'></span>
<textarea rows='1' class='form-control autosize step-steps' name='steps[]'></textarea>
<span class="input-group-addon">
<label class="checkbox-inline">
@@ -65,9 +65,7 @@
</span>
</div>
</td>
<td>
<textarea rows='1' class='form-control autosize step-expects' name='expects[]'></textarea>
</td>
<td><textarea rows='1' class='form-control autosize step-expects' name='expects[]'></textarea></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
@@ -78,21 +76,19 @@
</tr>
<?php foreach($case->steps as $stepID => $step):?>
<tr class='step'>
<td class='step-id'><input type='hidden' name='stepID[]' class='step-id-control'></td>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-child-id'></span>
<span class='input-group-addon step-item-id'></span>
<?php echo html::textarea('steps[]', $step->desc, "rows='1' class='form-control autosize step-steps'") ?>
<span class="input-group-addon">
<label class="checkbox-inline">
<input type='checkbox' name='stepType[]' value='parent' class='step-type'> <?php echo $lang->testcase->group ?>
<input type='checkbox' name='stepType[]' value='parent' class='step-type' <?php if($step->type == 'group') echo 'checked'?>> <?php echo $lang->testcase->group ?>
</label>
</span>
</div>
</td>
<td>
<?php echo html::textarea('expects[]', $step->expect, "rows='1' class='form-control autosize step-expects'") ?>
</td>
<td><?php echo html::textarea('expects[]', $step->expect, "rows='1' class='form-control autosize step-expects'") ?></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
+4 -3
View File
@@ -64,9 +64,10 @@
<?php if(isset($stepData[$key]['desc'])):?>
<table class='w-p100 bd-0'>
<?php foreach($stepData[$key]['desc'] as $id => $desc):?>
<tr>
<td><?php echo html::textarea("desc[$key][$id]", htmlspecialchars($desc), "class='form-control'")?></td>
<td><?php echo html::textarea("expect[$key][$id]", isset($stepData[$key]['expect'][$id]) ? htmlspecialchars($stepData[$key]['expect'][$id]) : '', "class='form-control'")?></td>
<tr class='step'>
<td><?php echo $id . html::hidden("stepType[$key][$id]", $desc['type'])?></td>
<td><?php echo html::textarea("desc[$key][$id]", htmlspecialchars($desc['content']), "class='form-control'")?></td>
<td><?php if($desc['type'] == 'item') echo html::textarea("expect[$key][$id]", isset($stepData[$key]['expect'][$id]['content']) ? htmlspecialchars($stepData[$key]['expect'][$id]['content']) : '', "class='form-control'")?></td>
</tr>
<?php endforeach;?>
</table>
+15 -4
View File
@@ -92,13 +92,24 @@
</tr>
</thead>
<?php
$stepId = $childId = 0;
foreach($case->steps as $stepID => $step)
{
$stepID += 1;
echo "<tr><th class='w-id text-center strong'>$stepID</th>";
echo "<td class='text-left'>" . nl2br($step->desc) . "</td>";
echo "<td class='text-left'>" . nl2br($step->expect) . "</td>";
$stepClass = "step-{$step->type}";
if($step->type == 'group' or ($step->type == 'item' and $step->parent == 0))
{
$stepId++;
$childId = 0;
}
if($step->type == 'item' and $step->parent == 0) $stepClass = 'step-group';
echo "<tr class='step {$stepClass}'>";
echo "<th class='step-id'>$stepId</th>";
echo "<td class='text-left'><div class='input-group'>";
if($step->type == 'item' and $step->parent != 0) echo "<span class='step-item-id'>{$stepId}.{$childId}</span>";
echo nl2br($step->desc) . "</td>";
echo "<td class='text-left'>" . nl2br($step->expect) . "</div></td>";
echo "</tr>";
$childId ++;
}
?>
</table>
+1
View File
@@ -523,6 +523,7 @@ class testsuite extends control
{
$paddingCount = $this->config->testcase->defaultSteps - count($steps);
$step = new stdclass();
$step->type = 'item';
$step->desc = '';
$step->expect = '';
for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step;
+32
View File
@@ -0,0 +1,32 @@
#steps .step-id {text-align: right}
#steps .step-item-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
#steps .checkbox-inline input[type="checkbox"] {top: -2px}
#steps .btn-group .btn {padding-left: 0; padding-right: 0; min-width: 30px;}
.step-actions {width: 100px;}
#steps .active td {transition: background-color .5s;}
#steps .step-group .step-steps {resize: none; max-height: 30px;}
#steps .step-group .step-expects {display: none;}
#steps .step-item .step-item-id {display: table-cell; min-width: 40px;}
#steps .step-item .step-id {color: transparent}
#steps .step-actions {width: 90px; text-align: center;}
#steps .btn-step-move {cursor: move}
#steps.sortable > tr.drag-shadow {display: none}
#steps.sortable-sorting > tr {transition: all .2s; position: relative; z-index: 5; opacity: .3;}
#steps.sortable-sorting {cursor: move;}
#steps.sortable-sorting > tr.drag-row {opacity: 1; z-index: 10; box-shadow: 0 2px 4px red}
#steps.sortable-sorting > tr.drag-row + tr > td {box-shadow: inset 0 4px 2px rgba(0,0,0,.2)}
#steps.sortable-sorting > tr.drag-row > td {background-color: #edf3fe!important}
#steps.sortable > tr.drop-success > td {background-color: #cfe0ff; transition: background-color 2s;}
.table-bordered .step-actions {width: 98px;}
.table-bordered > #steps > tr > td {padding: 0; background-color: #fafafa; border: 1px solid #ddd!important; border-left-style: dotted!important; border-right-style: dotted!important;}
.table-bordered > #steps > tr > td.step-id { padding-right: 8px;}
.table-bordered > #steps > tr > td .btn {border-color: transparent; background-color: transparent}
.table-bordered > #steps > tr > td .btn:hover,
.table-bordered > #steps > tr > td .btn:focus {background-color: #ddd}
.table-bordered > #steps .input-group-addon {border: none; background-color: transparent; border-left: 1px dotted #e5e5e5}
.table-bordered > #steps > tr > td textarea {border-color: #fff; box-shadow: none}
.table-bordered > #steps > tr > td textarea:hover {border-color: #808080;}
.table-bordered > #steps > tr > td textarea:focus {border-color: #4d90fe;}
.table-bordered > #steps .step-child .step-child-id {border-right: 1px dotted #ddd; border-left: none}
+114 -46
View File
@@ -1,19 +1,4 @@
var newRowID = 0;
function createRow()
{
if(newRowID == 0) newRowID = $('.stepID').size();
newRowID ++;
var newRow = "<tr class='text-center' id='row" + newRowID + "'>";
newRow += "<td class='stepID strong'></td>";
newRow += "<td><textarea name='steps[]' rows=1 class='form-control'></textarea></td>";
newRow += "<td><textarea name='expects[]' rows=1 class='form-control'></textarea></td>";
newRow += "<td class='text-left text-top'>";
newRow += "<button type='button' tabindex='-1' class='addbutton btn' title='" + lblBefore + "' onclick='preInsert(" + newRowID + ")' ><i class='icon icon-double-angle-up'></i></button>";
newRow += "<button type='button' tabindex='-1' class='addbutton btn' title='" + lblAfter + "' onclick='postInsert(" + newRowID + ")' ><i class='icon icon-double-angle-down'></i></button>";
newRow += "<button type='button' tabindex='-1' class='delbutton btn' title='" + lblDelete + "' onclick='deleteRow(" + newRowID + ")' ><i class='icon icon-remove'></i></button>";
newRow += "</td>";
return newRow;
}
function loadLibModules(libID)
{
@@ -26,43 +11,125 @@ function loadLibModules(libID)
}
/**
* Delete a step row.
* Init testcase steps in form
*
* @param int $rowID
* @param string selector
* @access public
* @return void
*/
function deleteRow(rowID)
function initSteps(selector)
{
if($('.stepID').size() == 1) return;
$('#row' + rowID).remove();
updateStepID();
}
if(navigator.userAgent.indexOf("Firefox") < 0)
{
$(document).on('input keyup paste change', 'textarea.autosize', function()
{
this.style.height = 'auto';
this.style.height = (this.scrollHeight + 2) + "px";
});
}
var $steps = $(selector || '#steps');
var $stepTemplate = $('#stepTemplate').detach().removeClass('template').attr('id', null);
var initSortableCallTask = null;
var groupNameText = $steps.data('groupName');
var insertStepRow = function($row, count)
{
if(count === undefined) count = 1;
for(var i = 0; i < count; ++i)
{
var $step = $stepTemplate.clone();
if($row) $row.after($step);
else $steps.append($step);
$step.addClass('step-new');
setTimeout(function(){$step.find('.step-steps').focus();}, 10);
/**
* Insert before the step.
*
* @param int $rowID
* @access public
* @return void
*/
function preInsert(rowID)
{
$('#row' + rowID).before(createRow());
updateStepID();
}
/**
* Insert after the step.
*
* @param int $rowID
* @access public
* @return void
*/
function postInsert(rowID)
{
$('#row' + rowID).after(createRow());
updateStepID();
}
};
var toggleStepRowType = function($row, toggleisGroup)
{
if(toggleisGroup === undefined) targetIsGroup = $row.find('.step-type').is(':checked');
$row.toggleClass('step-group', targetIsGroup);
$row.find('.step-steps').toggleClass('autosize', !targetIsGroup).attr('placeholder', targetIsGroup ? groupNameText : null).focus();
};
var refreshStepsID = function()
{
var parentId = 1, childId = 0;
$steps.children('.step:not(.drag-shadow)').each(function(idx)
{
var $step = $(this);
var isGroup = $step.find('.step-type').is(':checked');
var stepID;
if(isGroup || !childId)
{
$step.removeClass('step-item');
stepID = parentId++;
$step.find('.step-id').text(stepID);
if(isGroup) childId = 1;
}
else
{
stepID = (parentId - 1) + '.' + (childId++);
$step.addClass('step-item').find('.step-item-id').text(stepID);
}
$step.find('[name^="steps["]').attr('name', "steps[" +stepID + ']');
$step.find('[name^="stepType["]').attr('name', "stepType[" +stepID + ']');
$step.find('[name^="expects["]').attr('name', "expects[" +stepID + ']');
});
};
var initSortable = function()
{
var isMouseDown = false;
var $moveStep = null, moveOrder = 0;
$steps.on('mousedown', '.btn-step-move', function()
{
isMouseDown = true;
$moveStep = $(this).closest('.step').addClass('drag-row');
$(document).off('.sortable').one('mouseup.sortable', function()
{
isMouseDown = false;
$moveStep.removeClass('drag-row');
$steps.removeClass('sortable-sorting');
$moveStep = null;
});
$steps.addClass('sortable-sorting');
}).on('mouseenter', '.step:not(.drag-row)', function()
{
if(!isMouseDown) return;
var $targetStep = $(this);
$steps.children('.step').each(function(idx)
{
$(this).data('order', idx);
});
moveOrder = $moveStep.data('order');
var targetOrder = $targetStep.data('order');
if(moveOrder === targetOrder) return;
else if(targetOrder > moveOrder)
{
$targetStep.after($moveStep);
}
else if(targetOrder < moveOrder)
{
$targetStep.before($moveStep);
}
refreshStepsID();
});
}
$steps.on('click', '.btn-step-add', function()
{
insertStepRow($(this).closest('.step'));
refreshStepsID();
}).on('click', '.btn-step-delete', function()
{
if($('tbody#steps tr.step').size() == 1) return false;
$(this).closest('.step').remove();
refreshStepsID();
}).on('change', '.step-type', function()
{
toggleStepRowType($(this).closest('.step'));
refreshStepsID();
});
initSortable();
refreshStepsID();
}
/**
@@ -80,4 +147,5 @@ function updateStepID()
$(function()
{
$('[data-toggle=tooltip]').tooltip();
initSteps();
})
+50 -18
View File
@@ -105,31 +105,63 @@
<tr>
<th><?php echo $lang->testcase->steps;?></th>
<td colspan='2'>
<table class='table table-form mg-0' style='border: 1px solid #ddd'>
<table class='table table-form mg-0 table-bordered' style='border: 1px solid #ddd'>
<thead>
<tr>
<th class='w-40px'><?php echo $lang->testcase->stepID;?></th>
<th width="45%"><?php echo $lang->testcase->stepDesc;?></th>
<th><?php echo $lang->testcase->stepExpect;?></th>
<th class='w-140px'><?php echo $lang->actions;?></th>
<th class='step-actions'><?php echo $lang->actions;?></th>
</tr>
</thead>
<?php
foreach($steps as $stepID => $step)
{
$stepID += 1;
echo "<tr id='row$stepID' class='text-center'>";
echo "<td class='stepID strong'>$stepID</td>";
echo '<td>' . html::textarea('steps[]', $step->desc, "rows='1' class='form-control'") . '</td>';
echo '<td>' . html::textarea('expects[]', $step->expect, "rows='1' class='form-control'") . '</td>';
echo "<td class='text-left text-top'>";
echo "<button type='button' tabindex='-1' class='addbutton btn btn-xs' onclick='preInsert($stepID)' title='{$lang->testcase->insertBefore}'><i class=\"icon icon-double-angle-up\"></i></button>";
echo "<button type='button' tabindex='-1' class='addbutton btn btn-xs' onclick='postInsert($stepID)' title='{$lang->testcase->insertAfter}'><i class=\"icon icon-double-angle-down\"></i></button>";
echo "<button type='button' tabindex='-1' class='delbutton btn btn-xs' onclick='deleteRow($stepID)' title='{$lang->testcase->deleteStep}'><i class=\"icon icon-remove\"></i></button>";
echo "</td>";
echo '</tr>';
}
?>
<tbody id='steps' class='sortable' data-group-name='<?php echo $lang->testcase->groupName ?>'>
<tr class='template step' id='stepTemplate'>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-item-id'></span>
<textarea rows='1' class='form-control autosize step-steps' name='steps[]'></textarea>
<span class="input-group-addon">
<label class="checkbox-inline">
<input type='checkbox' name='stepType[]' value='parent' class='step-type'> <?php echo $lang->testcase->group ?>
</label>
</span>
</div>
</td>
<td><textarea rows='1' class='form-control autosize step-expects' name='expects[]'></textarea></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
<button type='button' class='btn btn-step-move'><i class='icon icon-move'></i></button>
<button type='button' class='btn btn-step-delete'><i class='icon icon-remove'></i></button>
</div>
</td>
</tr>
<?php foreach($steps as $stepID => $step):?>
<tr class='step'>
<td class='step-id'></td>
<td>
<div class='input-group'>
<span class='input-group-addon step-item-id'></span>
<?php echo html::textarea('steps[]', $step->desc, "rows='1' class='form-control autosize step-steps'") ?>
<span class="input-group-addon">
<label class="checkbox-inline">
<input type='checkbox' name='stepType[]' value='parent' class='step-type' <?php if($step->type == 'group') echo 'checked'?>> <?php echo $lang->testcase->group ?>
</label>
</span>
</div>
</td>
<td><?php echo html::textarea('expects[]', $step->expect, "rows='1' class='form-control autosize step-expects'") ?></td>
<td class='step-actions'>
<div class='btn-group'>
<button type='button' class='btn btn-step-add'><i class='icon icon-plus'></i></button>
<button type='button' class='btn btn-step-move'><i class='icon icon-move'></i></button>
<button type='button' class='btn btn-step-delete'><i class='icon icon-remove'></i></button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</td>
</tr>
+11
View File
@@ -1 +1,12 @@
body{background:white;}
.resultSteps .step-id {text-align: right}
.resultSteps .step-item-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
.resultSteps .checkbox-inline input[type="checkbox"] {top: -2px}
.resultSteps .btn-group .btn {padding-left: 0; padding-right: 0; min-width: 30px;}
.resultSteps .step-actions {width: 98px;}
.resultSteps .active td {transition: background-color .5s;}
.resultSteps .step-group .step-steps {resize: none; max-height: 30px;}
.resultSteps .step-group .step-expects {display: none;}
.resultSteps .step-item .step-item-id {display: table-cell;}
.resultSteps .step-item .step-id {color: transparent}
+22
View File
@@ -7,3 +7,25 @@
#filesName {float: right;}
.nav > li {margin-right: 5px; display: inline-block; margin-top: 5px;}
#steps .step-id {text-align: right}
#steps .step-item-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
#steps .checkbox-inline input[type="checkbox"] {top: -2px}
#steps .btn-group .btn {padding-left: 0; padding-right: 0; min-width: 30px;}
#steps .step-actions {width: 98px;}
#steps .active td {transition: background-color .5s;}
#steps .step-group .step-steps {resize: none; max-height: 30px;}
#steps .step-group .step-expects {display: none;}
#steps .step-item .step-item-id {display: table-cell;}
#steps .step-item .step-id {color: transparent}
.resultSteps .step-id {text-align: right}
.resultSteps .step-item-id {background-color: transparent; border: none; display: none; width: 30px; padding-left: 0; padding-right: 0; text-align: right; padding-right: 8px}
.resultSteps .checkbox-inline input[type="checkbox"] {top: -2px}
.resultSteps .btn-group .btn {padding-left: 0; padding-right: 0; min-width: 30px;}
.resultSteps .step-actions {width: 98px;}
.resultSteps .active td {transition: background-color .5s;}
.resultSteps .step-group .step-steps {resize: none; max-height: 30px;}
.resultSteps .step-group .step-expects {display: none;}
.resultSteps .step-item .step-item-id {display: table-cell;}
.resultSteps .step-item .step-id {color: transparent}
+36 -12
View File
@@ -594,33 +594,57 @@ class testtaskModel extends model
$relatedSteps = $this->dao->select('*')->from(TABLE_CASESTEP)
->where('`case`')->eq($runCaseID)
->andWhere('version')->in($relatedVersions)
->fetchAll();
->orderBy('id')
->fetchGroup('version', 'id');
$runs = $this->dao->select('t1.id,t2.build')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_TESTTASK)->alias('t2')->on('t1.task=t2.id')
->where('t1.id')->in($runIdList)
->fetchPairs();
$this->loadModel('file');
$files = $this->dao->select('*')->from(TABLE_FILE)
->where("(objectType = 'caseResult' or objectType = 'stepResult')")
->andWhere('objectID')->in(array_keys($results))
->andWhere('extra')->ne('editor')
->orderBy('id')
->fetchAll();
$resultFiles = array();
$stepFiles = array();
foreach($files as $file)
{
$file->webPath = $this->file->webPath . $file->pathname;
$file->realPath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname;
if($file->objectType == 'caseResult')
{
$resultFiles[$file->objectID][$file->id] = $file;
}
elseif($file->objectType == 'stepResult' and $file->extra !== '')
{
$stepFiles[$file->objectID][(int)$file->extra][$file->id] = $file;
}
}
foreach($results as $resultID => $result)
{
$result->stepResults = unserialize($result->stepResults);
$result->build = $result->run ? zget($runs, $result->run, 0) : 0;
$result->files = $this->loadModel('file')->getByObject('caseResult', $resultID);//Get files of case result.
$results[$resultID] = $result;
foreach($relatedSteps as $key => $step)
$result->files = zget($resultFiles, $resultID, array()); //Get files of case result.
if(isset($relatedSteps[$result->version]))
{
if($result->version == $step->version)
$relatedStep = $relatedSteps[$result->version];
foreach($relatedStep as $stepID => $step)
{
$result->stepResults[$step->id]['desc'] = $step->desc;
$result->stepResults[$step->id]['expect'] = $step->expect;
$relatedStep[$stepID] = (array)$step;
if(isset($result->stepResults[$stepID]))
{
$relatedStep[$stepID]['result'] = $result->stepResults[$stepID]['result'];
$relatedStep[$stepID]['real'] = $result->stepResults[$stepID]['real'];
}
}
$result->stepResults = $relatedStep;
}
/* Get files of step result. */
foreach($result->stepResults as $stepID => $stepResult)
{
$result->stepResults[$stepID]['files'] = $this->loadModel('file')->getByObject('stepResult', $resultID, $stepID);
}
foreach($result->stepResults as $stepID => $stepResult) $result->stepResults[$stepID]['files'] = isset($stepFiles[$resultID][$stepID]) ? $stepFiles[$resultID][$stepID] : array();
}
return $results;
}
+23 -9
View File
@@ -49,7 +49,7 @@
</tr>
<tr class='result-detail hide'>
<td colspan='7' class='pd-0'>
<table class='table table-condensed borderless mg-0'>
<table class='table table-condensed borderless mg-0 resultSteps'>
<thead>
<tr>
<th class='w-40px'><?php echo $lang->testcase->stepID;?></th>
@@ -58,32 +58,46 @@
<th class='w-p10 text-left'><?php echo $lang->testcase->stepVersion;?></th>
<th class='text-center'><?php echo $lang->testcase->result;?></th>
<th class='w-p20 text-left'><?php echo $lang->testcase->real;?></th>
<th class='w-50px'></th>
<th class='w-80px'></th>
</tr>
</thead>
<?php
$i = 1;
$stepId = $childId = 0;
foreach($result->stepResults as $key => $stepResult):
?>
<?php
if(empty($stepResult['type'])) $stepResult['type'] = 'item';
if(empty($stepResult['parent'])) $stepResult['parent'] = 0;
$stepClass = "step-{$stepResult['type']}";
if($stepResult['type'] == 'group' or ($stepResult['type'] == 'item' and $stepResult['parent'] == 0))
{
$stepId++;
$childId = 0;
}
if($stepResult['type'] == 'item' and $stepResult['parent'] == 0) $stepClass = 'step-group';
$modalID = $result->id . '-' . $key;
$fileCount = '(' . count($stepResult['files']) . ')';
?>
<tr>
<td class='w-30px text-center'><?php echo $i;?></td>
<td><?php if(isset($stepResult['desc'])) echo nl2br($stepResult['desc']);?></td>
<td><?php if(isset($stepResult['expect'])) echo nl2br($stepResult['expect']);?></td>
<tr class='step <?php echo $stepClass?>'>
<td class='step-id'><?php echo $stepId;?></td>
<td class='text-left' <?php if($stepResult['type'] == 'group') echo "colspan='6'"?>>
<div class='input-group'>
<?php if($stepResult['type'] == 'item' and $stepResult['parent'] != 0) echo "<span class='step-item-id'>{$stepId}.{$childId}</span>";?>
<?php if(isset($stepResult['desc'])) echo nl2br($stepResult['desc']);?>
</div>
</td>
<?php if($stepResult['type'] != 'group'):?>
<td class='text-left'><?php if(isset($stepResult['expect'])) echo nl2br($stepResult['expect']);?></td>
<td><?php if(isset($result->version)) echo nl2br($result->version);?></td>
<?php if(!empty($stepResult['result'])):?>
<td class='<?php echo $stepResult['result'];?> text-center'><?php echo $lang->testcase->resultList[$stepResult['result']];?></td>
<td><?php echo $stepResult['real'];?></td>
<td class='text-center'><?php if(!empty($stepResult['files'])) echo html::a("#stepResult{$modalID}", $lang->files . $fileCount, '', "data-toggle='modal' data-type='iframe'")?></td>
</tr>
<?php else:?>
<td></td>
<td></td>
<?php endif; endif; $childId++;?>
</tr>
<?php endif; $i++;?>
<?php endforeach;?>
</table>
</td>
+25 -5
View File
@@ -20,7 +20,7 @@
</div>
<div class='main'>
<form class='form-condensed' method='post' enctype='multipart/form-data'>
<table class='table table-bordered table-form' style='word-break:break-all'>
<table class='table table-bordered table-form' style='word-break:break-all' id='steps'>
<thead>
<tr>
<td colspan='5' style='word-break: break-all;'><strong><?php echo $lang->testcase->precondition;?></strong> <?php echo $run->case->precondition;?></td>
@@ -38,17 +38,35 @@
{
$step = new stdclass();
$step->id = 0;
$step->parent = 0;
$step->case = $run->case->id;
$step->type = 'item';
$step->desc = '';
$step->expect = '';
$run->case->steps[] = $step;
}
$stepId = $childId = 0;
?>
<?php foreach($run->case->steps as $key => $step):?>
<tr>
<th><?php echo $key + 1;?></th>
<td><?php echo nl2br($step->desc);?></td>
<td><?php echo nl2br($step->expect);?></td>
<?php
$stepClass = "step-{$step->type}";
if($step->type == 'group' or ($step->type == 'item' and $step->parent == 0))
{
$stepId++;
$childId = 0;
}
if($step->type == 'item' and $step->parent == 0) $stepClass = 'step-group';
?>
<tr class='step <?php echo $stepClass?>'>
<th class='step-id'><?php echo $stepId;?></th>
<td class='text-left' <?php if($step->type == 'group') echo "colspan='4'"?>>
<div class='input-group'>
<?php if($step->type == 'item' and $step->parent != 0) echo "<span class='step-item-id'>{$stepId}.{$childId}</span>";?>
<?php echo nl2br($step->desc);?>
</div>
</td>
<?php if($step->type != 'group'):?>
<td class='text-left'><?php echo nl2br($step->expect);?></td>
<td class='text-center'><?php echo html::select("steps[$step->id]", $lang->testcase->resultList, 'pass', "class='form-control'");?></td>
<td>
<table class='w-p100 fix-border fix-position'>
@@ -58,7 +76,9 @@
</tr>
</table>
</td>
<?php endif;?>
</tr>
<?php $childId ++;?>
<?php endforeach;?>
<tr class='text-center'>
<td colspan='5'>