diff --git a/module/bug/model.php b/module/bug/model.php index 05e88ca170..13e36faf2e 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1323,7 +1323,7 @@ class bugModel extends model if(!$executionID and $caseID > 0) $executionID = isset($run->case->execution) ? $run->case->execution : 0; // Fix feedback #1043. if(!$executionID and $this->app->tab == 'execution') $executionID = $this->session->execution; - return array('title' => $run->case->title, 'steps' => $bugSteps, 'storyID' => $run->case->story, 'moduleID' => $run->case->module, 'version' => $run->case->version, 'executionID' => $executionID); + return array('title' => $run->case->title, 'caseID' => $caseID, 'steps' => $bugSteps, 'storyID' => $run->case->story, 'moduleID' => $run->case->module, 'version' => $run->case->version, 'executionID' => $executionID); } /** diff --git a/module/testcase/css/createbug.ui.css b/module/testcase/css/createbug.ui.css new file mode 100644 index 0000000000..71ba86a1f3 --- /dev/null +++ b/module/testcase/css/createbug.ui.css @@ -0,0 +1,9 @@ +.form-row.form-row-group {border-bottom: unset;} +#casesResults .result-detail .steps-header > div {font-size: 13px; color: var(--color-slate-700); padding: 8px;} +#casesResults .result-detail .steps-header > div.desc {padding-left: 32px;} +#casesResults .result-detail .fail .steps-header > div.desc {padding-left: 52px;} +#casesResults .result-detail .steps-body > .step:last-child {border-bottom: 0;} +#casesResults .result-detail .steps-body > .step > div {padding: 8px;} +#casesResults .result-item {background-color: var(--color-slate-50); border-color: rgba(var(--color-gray-300-rgb), 0.7);} +#casesResults .result-detail > td {padding: 0;} +#casesResults .step-item-id {color: var(--color-slate-500);} diff --git a/module/testcase/js/createbug.ui.js b/module/testcase/js/createbug.ui.js index 0aa39dbb82..32468b250f 100644 --- a/module/testcase/js/createbug.ui.js +++ b/module/testcase/js/createbug.ui.js @@ -1,11 +1,26 @@ $(function() { - loadCurrentPage({url: resultsLink, selector: '#casesResults', partial: true}); + loadCurrentPage + ({ + url: resultsLink, + selector: '#casesResults', + partial: true, + success : function() + { + var $resultTrs = $('#resultsContainer').find('#casesResults tr'); + if($resultTrs.length == 0) return false; + + if($resultTrs.first().data('status') == 'ready') + { + $resultTrs.first().trigger('click'); + } + } + }); $('#resultsContainer').off('click', '.result-item').on('click', '.result-item', toggleShowResults); $('#resultsContainer').off('click', '.check-all').on('click', '.check-all', toggleCheckAll); $('#resultsContainer').off('click', '.check-item').on('click', '.check-item', toggleCheckChildItem); - $('#resultsContainer').off('click', '.to-bug-button').on('click', '.to-bug-button', toggleCheckChildItem); + $('#resultsContainer').off('click', '.to-bug-button').on('click', '.to-bug-button', createBug); }); /** @@ -18,14 +33,14 @@ $(function() function toggleShowResults(event) { var $target = $(event.target).closest('tr'); - if($target.data('status') == 'running') return; + $target.toggleClass('is-collapsed'); + $target.toggleClass('is-expanded'); $target.toggleClass('show-detail'); - var show = $target.hasClass('show-detail'); $target.next('.result-detail').toggleClass('hidden', !show); - $target.find('.collapse-handle').toggleClass('icon-angle-down', !show).toggleClass('icon-angle-top', show);; + $target.find('.collapse-handle').toggleClass('icon-angle-down', !show).toggleClass('icon-angle-top', show); } /** @@ -44,7 +59,8 @@ function createBug(event) if($(this).prop('checked')) stepIdList += $(this).val() + '_'; }); - $form.attr('action', $.createLink('bug', 'create', bugCreateParams + ',stepIdList=' + stepIdList)); + var link = $.createLink('bug', 'create', $form.data('params') + ',stepIdList=' + stepIdList); + loadPage(link); } /** @@ -56,11 +72,10 @@ function createBug(event) */ function toggleCheckAll(event) { - var $checkAll = $(event.target).closest('td').find("input[type='checkbox']"); - var isChecked = !$checkAll.prop('checked'); - $checkAll.prop('checked', isChecked); + var $checkAll = $(event.target).closest('.check-all').find("input[type='checkbox']"); + var isChecked = $checkAll.prop('checked'); - $checkAll.closest('tbody').children('tr').find('input[type=checkbox]').prop('checked', isChecked); + $checkAll.closest('.resultSteps').find('.step').find('input[type=checkbox]').prop('checked', isChecked); } /** @@ -72,27 +87,36 @@ function toggleCheckAll(event) */ function toggleCheckChildItem(event) { - var $target = $(event.target).closest('td').find("input[type='checkbox']"); - var isChecked = !$target.prop('checked'); - $target.prop('checked', isChecked); + var $target = $(event.target).closest('.step-id').find("input[type='checkbox']"); + var $step = $target.closest('.step'); + var isChecked = $target.prop('checked'); - var $next = $target.closest('tr').next(); - - while($target.closest('tr').hasClass('step-group') && $next.length && $next.hasClass('step-item')) + var grade = $step.data('grade'); + var $next = $target.closest('.step').next(); + while(grade < $next.data('grade')) { $next.find("input[type='checkbox']").prop('checked', isChecked); $next = $next.next(); } - if($target.closest('tr').hasClass('step-item')) + var parentStepID = $step.data('parent'); + if($step.data('id') != 0 && parentStepID != 0) { - var parentStepKey = $target.closest('tr').data('parent'); - var allSiblings = $target.closest('tbody').find('.step-item.group-' + parentStepKey).length - var checkedSiblings = $target.closest('tbody').find('.step-item.group-' + parentStepKey + ' input[type=checkbox]:checked').length - - $target.closest('tr').prevAll('.step-group').first().find('input[type=checkbox]').prop('checked', allSiblings == checkedSiblings); + var allSiblings = $target.closest('.steps-body').find('[data-parent="' + parentStepID + '"]').length + var checkedSiblings = $target.closest('.steps-body').find('[data-parent="' + parentStepID + '"]' + ' input[type=checkbox]:checked').length + var $parentStep = $target.closest('.step').prevAll('[data-id="' + parentStepID + '"]').find('input[type=checkbox]'); + var siblingsChecked = !!(allSiblings == checkedSiblings); + if(!$parentStep.prop('checked') && siblingsChecked) + { + $parentStep.trigger('click'); + } + else + { + $parentStep.prop('checked', false); + if($parentStep.closest('.step').data('parent') != 0) $target.closest('.step').prevAll('[data-id="' + $parentStep.closest('.step').data('parent') + '"]').find('input[type=checkbox]').prop('checked', false); + } } - var $tbody = $target.closest('tbody'); - $tbody.find('.check-all input[type=checkbox]').prop('checked', $tbody.find('.check-item input[type=checkbox]').length == $tbody.find('.check-item input[type=checkbox]:checked').length); + var $resultSteps = $target.closest('.resultSteps'); + $resultSteps.find('.check-all input[type=checkbox]').prop('checked', $resultSteps.find('.check-item input[type=checkbox]').length == $resultSteps.find('.check-item input[type=checkbox]:checked').length); } diff --git a/module/testcase/ui/createbug.html.php b/module/testcase/ui/createbug.html.php index 6b03a06750..77b42da61f 100644 --- a/module/testcase/ui/createbug.html.php +++ b/module/testcase/ui/createbug.html.php @@ -10,7 +10,7 @@ declare(strict_types=1); */ namespace zin; -jsVar('resultsLink', createLink('testtask', 'results', "runID={$runID}&caseID={$caseID}&version={$version}") . '#casesResults'); +jsVar('resultsLink', createLink('testtask', 'results', "runID={$runID}&caseID={$caseID}&version={$version}&status=all&result=fail") . '#casesResults'); set::title($lang->testcase->createBug); diff --git a/module/testtask/control.php b/module/testtask/control.php index d04e6a35c0..5555a13c3e 100644 --- a/module/testtask/control.php +++ b/module/testtask/control.php @@ -1427,17 +1427,18 @@ class testtask extends control * @param int $caseID * @param int $version * @param string $status all|done + * @param string $type all|fail * @access public * @return void */ - public function results($runID, $caseID = 0, $version = 0, $status = 'done') + public function results($runID, $caseID = 0, $version = 0, $status = 'done', $type = 'all') { if($this->app->tab == 'project') $this->loadModel('project')->setMenu($this->session->project); if($runID) { $case = $this->testtask->getRunById($runID)->case; - $results = $this->testtask->getResults($runID, 0, $status); + $results = $this->testtask->getResults($runID, 0, $status, $type); $testtaskID = $this->dao->select('task')->from(TABLE_TESTRUN)->where('id')->eq($runID)->fetch('task'); $testtask = $this->dao->select('id, build, execution, product')->from(TABLE_TESTTASK)->where('id')->eq($testtaskID)->fetch(); @@ -1447,13 +1448,14 @@ class testtask extends control else { $case = $this->loadModel('testcase')->getByID($caseID, $version); - $results = $this->testtask->getResults(0, $caseID, $status); + $results = $this->testtask->getResults(0, $caseID, $status, $type); } if(empty($this->testcase)) $this->app->loadLang('testcase'); $this->view->case = $case; $this->view->runID = $runID; $this->view->results = $results; + $this->view->type = $type; $this->view->builds = $this->loadModel('build')->getBuildPairs($case->product, $case->branch); $this->view->users = $this->loadModel('user')->getPairs('noclosed, noletter'); $this->view->testtasks = $this->testtask->getPairs($case->product); diff --git a/module/testtask/js/common.ui.js b/module/testtask/js/common.ui.js index a0b2254cad..0d46b9f5f5 100644 --- a/module/testtask/js/common.ui.js +++ b/module/testtask/js/common.ui.js @@ -3,7 +3,7 @@ $(function() $('#resultsContainer').off('click', '.result-item').on('click', '.result-item', toggleShowResults); $('#resultsContainer').off('click', '.check-all').on('click', '.check-all', toggleCheckAll); $('#resultsContainer').off('click', '.check-item').on('click', '.check-item', toggleCheckChildItem); - $('#resultsContainer').off('click', '.to-bug-button').on('click', '.to-bug-button', toggleCheckChildItem); + $('#resultsContainer').off('click', '.to-bug-button').on('click', '.to-bug-button', createBug); }); /** @@ -96,12 +96,13 @@ function createBug(event) { var $form = $(event.target).closest('form'); var stepIdList = ''; - $form.find('.step .step-id input[type="checkbox"]:checked').each(function() + $(event.target).closest('form').find('.step .step-id input[type="checkbox"]:checked').each(function() { if($(this).prop('checked')) stepIdList += $(this).val() + '_'; }); - $form.attr('action', $.createLink('bug', 'create', bugCreateParams + ',stepIdList=' + stepIdList)); + var link = $.createLink('bug', 'create', $form.data('params') + ',stepIdList=' + stepIdList); + loadPage(link); } /** @@ -115,6 +116,7 @@ function toggleShowResults(event) { var $target = $(event.target).closest('tr'); if($target.data('status') == 'running') return; + $target.toggleClass('is-collapsed'); $target.toggleClass('is-expanded'); $target.toggleClass('show-detail'); @@ -151,22 +153,32 @@ function toggleCheckChildItem(event) var $step = $target.closest('.step'); var isChecked = $target.prop('checked'); - var stepID = $step.data('id'); + var grade = $step.data('grade'); var $next = $target.closest('.step').next(); - while(stepID == $next.data('parent')) + while(grade < $next.data('grade')) { $next.find("input[type='checkbox']").prop('checked', isChecked); $next = $next.next(); } - if(stepID != 0) + var parentStepID = $step.data('parent'); + if($step.data('id') != 0 && parentStepID != 0) { - var parentStepID = $step.data('parent'); var allSiblings = $target.closest('.steps-body').find('[data-parent="' + parentStepID + '"]').length var checkedSiblings = $target.closest('.steps-body').find('[data-parent="' + parentStepID + '"]' + ' input[type=checkbox]:checked').length - $target.closest('.step').prevAll('[data-id="' + parentStepID + '"]').find('input[type=checkbox]').prop('checked', allSiblings == checkedSiblings); + var $parentStep = $target.closest('.step').prevAll('[data-id="' + parentStepID + '"]').find('input[type=checkbox]'); + var siblingsChecked = !!(allSiblings == checkedSiblings); + if(!$parentStep.prop('checked') && siblingsChecked) + { + $parentStep.trigger('click'); + } + else + { + $parentStep.prop('checked', false); + if($parentStep.closest('.step').data('parent') != 0) $target.closest('.step').prevAll('[data-id="' + $parentStep.closest('.step').data('parent') + '"]').find('input[type=checkbox]').prop('checked', false); + } } - var $stepsBody = $target.closest('.steps-body'); - $stepsBody.find('.check-all input[type=checkbox]').prop('checked', $stepsBody.find('.check-item input[type=checkbox]').length == $stepsBody.find('.check-item input[type=checkbox]:checked').length); + var $resultSteps = $target.closest('.resultSteps'); + $resultSteps.find('.check-all input[type=checkbox]').prop('checked', $resultSteps.find('.check-item input[type=checkbox]').length == $resultSteps.find('.check-item input[type=checkbox]:checked').length); } diff --git a/module/testtask/model.php b/module/testtask/model.php index 9607eb41ec..7ac4a4f609 100755 --- a/module/testtask/model.php +++ b/module/testtask/model.php @@ -1417,16 +1417,18 @@ class testtaskModel extends model * @param int $runID * @param int $caseID * @param string $status all|done + * @param string $type all|fail * @access public * @return void */ - public function getResults($runID, $caseID = 0, $status = 'all') + public function getResults($runID, $caseID = 0, $status = 'all', $type = 'all') { if($runID > 0) { $results = $this->dao->select('*')->from(TABLE_TESTRESULT) ->where('run')->eq($runID) ->beginIF($status == 'done')->andWhere('caseResult')->ne('')->fi() + ->beginIF($type != 'all')->andWhere('caseResult')->eq($type)->fi() ->orderBy('id desc') ->fetchAll('id'); } @@ -1435,6 +1437,7 @@ class testtaskModel extends model $results = $this->dao->select('*')->from(TABLE_TESTRESULT) ->where('`case`')->eq($caseID) ->beginIF($status == 'done')->andWhere('caseResult')->ne('')->fi() + ->beginIF($type != 'all')->andWhere('caseResult')->eq($type)->fi() ->orderBy('id desc') ->fetchAll('id'); } diff --git a/module/testtask/ui/results.html.php b/module/testtask/ui/results.html.php index a730b64d20..53326a1a32 100644 --- a/module/testtask/ui/results.html.php +++ b/module/testtask/ui/results.html.php @@ -127,15 +127,17 @@ foreach($results as $i => $result) $stepResultTrs[] = div ( - setClass("step flex border-b step-item "), + setClass("step flex border-b step-{$stepResult['type']} "), set('data-parent', $stepResult['parent']), + set('data-grade', $stepResult['grade']), set('data-id', $key), div ( - setClass('step-id flex border-r'), + setClass('step-id flex border-r check-item'), width('calc(75% - 378px)'), $result->caseResult == 'fail' ? checkbox ( + on::click('toggleCheckChildItem'), set::id("stepIdList[{$stepResult['id']}]"), set('name', "stepIdList[{$stepResult['id']}]"), set('value', $key), @@ -175,11 +177,10 @@ foreach($results as $i => $result) h::td ( setClass('pd-0'), - h::form + form ( - setClass('form load-indicator form-ajax form-grid'), set('data-params', $linkParams), - set('action', createLink('bug', 'create', $linkParams)), + set::actions(array()), div ( setClass('resultSteps ' . $result->caseResult), @@ -235,15 +236,12 @@ foreach($results as $i => $result) ), div ( - setClass('to-bug-button ml-8'), btn ( - setClass('btn h-7 px-6'), + setClass('btn h-7 px-6 ml-8 to-bug-button'), set::type('primary'), - set::btnType('btnType'), + set('data-dismiss', 'modal'), on::click('createBug'), - set('data-target', '_blank'), - set('data-close-modal', true), $lang->testcase->createBug ), ), @@ -269,9 +267,9 @@ div ( div ( - setClass('main pt-6'), + setClass('main' . ($type != 'fail' ? ' mt-6' : '')), set::id('casesResults'), - $case->auto != 'unit' ? formRowGroup + $case->auto != 'unit' && $type != 'fail' ? formRowGroup ( set::title($lang->testcase->result), set::items @@ -287,7 +285,6 @@ div $fileModals, ), ); -jsVar('bugCreateParams', $linkParams); render();