VirtualBox

Ignore:
Timestamp:
May 26, 2016 8:04:05 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107506
Message:

testmanager: give reason to failures (quick hack, can do prettier later).

Location:
trunk/src/VBox/ValidationKit/testmanager/webui
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmin.py

    r56295 r61217  
    138138
    139139    ksActionFailureReasonList       = 'FailureReasonList'
     140    ksActionFailureReasonDetails    = 'FailureReasonDetails'
    140141    ksActionFailureReasonShowAdd    = 'FailureReasonShowAdd'
    141142    ksActionFailureReasonShowEdit   = 'FailureReasonShowEdit'
     
    365366                                                                WuiAdminFailureReasonList)
    366367
    367         d[self.ksActionFailureReasonShowAdd]    = lambda: self._actionGenericFormAdd(
    368                                                                 FailureReasonData,
    369                                                                 WuiAdminFailureReason)
    370 
     368        d[self.ksActionFailureReasonDetails]    = lambda: self._actionGenericFormDetails(FailureReasonData,
     369                                                                                         FailureReasonLogic,
     370                                                                                         WuiAdminFailureReason,
     371                                                                                         'idFailureReason');
    371372        d[self.ksActionFailureReasonShowEdit]   = lambda: self._actionGenericFormEditL(
    372373                                                                FailureReasonLogic,
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuibase.py

    r56295 r61217  
    7474    ## The name of the effective date (timestamp) parameter.
    7575    ksParamEffectiveDate = 'EffectiveDate';
     76
     77    ## The name of the redirect-to (test manager relative url) parameter.
     78    ksParamRedirectTo    = 'RedirectTo';
    7679
    7780    ## The name of the list-action parameter (WuiListContentWithActionBase).
     
    546549        return str(oDate);
    547550
     551    def getRedirectToParameter(self, sDefault = None):
     552        """
     553        Gets the special redirect to parameter if it exists, will Return default
     554        if not, with None being a valid default.
     555
     556        Makes sure the it doesn't got offsite.
     557        Raises exception if invalid.
     558        """
     559        if sDefault is not None or self.ksParamRedirectTo in self._dParams:
     560            sValue = self.getStringParam(self.ksParamRedirectTo, sDefault = sDefault);
     561            cch = sValue.find("?");
     562            if cch < 0:
     563                cch = sValue.find("#");
     564                if cch < 0:
     565                    cch = len(sValue);
     566            for ch in (':', '/', '\\', '..'):
     567                if sValue.find(ch, 0, cch) >= 0:
     568                    raise WuiException('Invalid character (%c) in redirect-to url: %s' % (ch, sValue,));
     569        else:
     570            sValue = None;
     571        return sValue;
     572
    548573
    549574    def _checkForUnknownParameters(self):
     
    701726        return True;
    702727
    703     def _actionGenericFormAdd(self, oDataType, oFormType):
     728    def _actionGenericFormAdd(self, oDataType, oFormType, sRedirectTo = None):
    704729        """
    705730        Generic add something form display request handler.
     
    709734        """
    710735        oData = oDataType().initFromParams(oDisp = self, fStrict = False);
     736        sRedirectTo = self.getRedirectToParameter(sRedirectTo);
    711737        self._checkForUnknownParameters();
    712738
    713739        oForm = oFormType(oData, oFormType.ksMode_Add, oDisp = self);
     740        oForm.setRedirectTo(sRedirectTo);
    714741        (self._sPageTitle, self._sPageBody) = oForm.showForm();
    715742        return True
     
    757784
    758785
    759     def _actionGenericFormEdit(self, oDataType, oFormType, sIdParamName):
     786    def _actionGenericFormEdit(self, oDataType, oFormType, sIdParamName, sRedirectTo = None):
    760787        """
    761788        Generic edit something form display request handler.
     
    766793        """
    767794
     795        tsNow    = self.getEffectiveDateParam();
    768796        idObject = self.getIntParam(sIdParamName, 0, 0x7ffffffe);
     797        sRedirectTo = self.getRedirectToParameter(sRedirectTo);
    769798        self._checkForUnknownParameters();
    770         oData = oDataType().initFromDbWithId(self._oDb, idObject);
     799        oData = oDataType().initFromDbWithId(self._oDb, idObject, tsNow = tsNow);
    771800
    772801        oContent = oFormType(oData, oFormType.ksMode_Edit, oDisp = self);
     802        oContent.setRedirectTo(sRedirectTo);
    773803        (self._sPageTitle, self._sPageBody) = oContent.showForm();
    774804        return True
     
    850880        #
    851881        oData = oDataType().initFromParams(oDisp = self, fStrict = fStrict);
     882        sRedirectTo = self.getRedirectToParameter(sRedirectTo);
    852883        self._checkForUnknownParameters();
    853884        self._assertPostRequest();
     
    864895                self._oDb.rollback();
    865896                oForm = oFormType(oData, sMode, oDisp = self);
     897                oForm.setRedirectTo(sRedirectTo);
    866898                sErrorMsg = str(oXcpt) if not config.g_kfDebugDbXcpt else '\n'.join(utils.getXcptInfo(4));
    867899                (self._sPageTitle, self._sPageBody) = oForm.showForm(sErrorMsg = sErrorMsg);
     
    961993            self._sAction = self.ksActionDefault;
    962994
    963         if self._sAction not in self._dDispatch:
     995        if isinstance(self._sAction, list) or  self._sAction not in self._dDispatch:
    964996            raise WuiException('Unknown action "%s" requested' % (self._sAction,));
    965997
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py

    r56807 r61217  
    190190
    191191    ## The text/symbol for a very short edit link.
    192     ksShortEditLink    = u'\u270D'
     192    ksShortEditLink        = u'\u270D'
     193    ## HTML hex entity string for ksShortDetailsLink.
     194    ksShortEditLinkHtml    = '&#x270d;'
    193195    ## The text/symbol for a very short details link.
    194     ksShortDetailsLink = u'\u2318'
     196    ksShortDetailsLink     = u'\u2318'
     197    ## HTML hex entity string for ksShortDetailsLink.
     198    ksShortDetailsLinkHtml = '&#x2318;'
    195199
    196200
     
    327331        if sSubmitAction is None and sMode != self.ksMode_Show:
    328332            self._sSubmitAction = getattr(oDisp, self._sActionBase + self.kdSubmitActionMappings[sMode]);
     333        self._sRedirectTo   = None;
    329334
    330335
     
    469474                       '</div>\n';
    470475        return sNavigation;
     476
     477    def setRedirectTo(self, sRedirectTo):
     478        """
     479        For setting the hidden redirect-to field.
     480        """
     481        self._sRedirectTo = sRedirectTo;
     482        return True;
    471483
    472484    def showChangeLog(self, aoEntries, fMoreEntries, iPageNo, cEntriesPerPage, tsNow, fShowNavigation = True):
     
    521533        try:
    522534            self._populateForm(oForm, self._oData);
     535            if self._sRedirectTo is not None:
     536                oForm.addTextHidden(self._oDisp.ksParamRedirectTo, self._sRedirectTo);
    523537        except WuiException, oXcpt:
    524538            sContent = unicode(oXcpt)
     
    558572                dParams[WuiDispatcherBase.ksParamEffectiveDate] = self._oData.tsEffective;
    559573                dParams[getattr(self._oData, 'ksParam_' + self._oData.ksIdAttr)] = getattr(self._oData, self._oData.ksIdAttr);
    560             dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Edit');
     574            dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Details');
    561575            aoActions.append(WuiTmLink('Details', '', dParams));
    562576
     
    629643        assert len(aoValues) == len(self._asColumnHeaders), '%s vs %s' % (len(aoValues), len(self._asColumnHeaders));
    630644
    631         for i in range(len(aoValues)):
     645        for i, _ in enumerate(aoValues):
    632646            if i < len(self._asColumnAttribs) and len(self._asColumnAttribs[i]) > 0:
    633647                sRow += u'    <td ' + self._asColumnAttribs[i] + '>';
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py

    r56295 r61217  
    4848    ksItemsList = 'ksItemsList'
    4949
    50     def __init__(self, sId, sAction, dErrors = None, fReadOnly = False):
     50    ksOnSubmit_AddReturnToFieldWithCurrentUrl = '+AddReturnToFieldWithCurrentUrl+';
     51
     52    def __init__(self, sId, sAction, dErrors = None, fReadOnly = False, sOnSubmit = None):
    5153        self._fFinalized = False;
    5254        self._fReadOnly  = fReadOnly;
    5355        self._dErrors    = dErrors if dErrors is not None else dict();
     56
     57        if sOnSubmit == self.ksOnSubmit_AddReturnToFieldWithCurrentUrl:
     58            sOnSubmit = 'return addRedirectToInputFieldWithCurrentUrl(this)';
     59        if sOnSubmit is None:   sOnSubmit = u'';
     60        else:                   sOnSubmit = u' onsubmit=\"%s\"' % (escapeAttr(sOnSubmit),);
     61
    5462        self._sBody      = u'\n' \
    5563                           u'<div id="%s" class="tmform">\n' \
    56                            u'  <form action="%s" method="post">\n' \
     64                           u'  <form action="%s" method="post"%s>\n' \
    5765                           u'    <ul>\n' \
    58                          % (sId, sAction);
     66                         % (sId, sAction, sOnSubmit);
    5967
    6068    def _add(self, sText):
     
    7078        if sText.find('<br>') >= 0:
    7179            asParts = sText.split('<br>');
    72             for i in range(len(asParts)):
     80            for i, _ in enumerate(asParts):
    7381                asParts[i] = escapeElem(asParts[i].strip());
    7482            sText = '<br>\n'.join(asParts);
     
    114122                         '    </li>\n'
    115123                         % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(str(sValue)) ));
     124    #
     125    # Non-input stuff.
     126    #
     127    def addNonText(self, sValue, sLabel, sPostHtml = ''):
     128        """Adds a read-only text input."""
     129        self._addLabel('non-text', sLabel, 'string');
     130        if sValue is None: sValue = '';
     131        return self._add('          <p>%s</p>%s\n'
     132                         '        </div></div>\n'
     133                         '      </li>\n'
     134                         % (escapeElem(str(sValue)), sPostHtml ));
     135
    116136
    117137    #
     
    124144        if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
    125145        self._addLabel(sName, sLabel, sSubClass);
     146        if sValue is None: sValue = '';
    126147        return self._add('          <input name="%s" id="%s" type="text"%s value="%s">%s\n'
    127148                         '        </div></div>\n'
     
    133154        if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
    134155        self._addLabel(sName, sLabel, sSubClass);
     156        if sValue is None: sValue = '';
    135157        return self._add('          <input name="%s" id="%s" type="text" readonly%s value="%s" class="tmform-input-readonly">%s\n'
    136158                         '        </div></div>\n'
     
    153175        if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
    154176        self._addLabel(sName, sLabel, sSubClass)
     177        if sValue is None: sValue = '';
    155178        sNewValue = str(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
    156179        return self._add('          <textarea name="%s" id="%s" %s>%s</textarea>\n'
     
    163186        if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
    164187        self._addLabel(sName, sLabel, sSubClass)
     188        if sValue is None: sValue = '';
    165189        sNewValue = str(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
    166190        return self._add('          <textarea name="%s" id="%s" readonly %s>%s</textarea>\n'
     
    213237        self._add('          <select name="%s" id="%s" class="tmform-combobox"%s>\n'
    214238                  % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
     239        sSelected = str(sSelected);
    215240        for iValue, sText, _ in aoOptions:
    216241            sValue = str(iValue);
    217242            self._add('            <option value="%s"%s>%s</option>\n'
    218                       % (escapeAttr(sValue), ' selected' if sValue == str(sSelected) else '',
     243                      % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
    219244                         escapeElem(sText)));
    220245        return self._add('          </select>\n'
     
    229254        self._add('          <select name="%s" id="%s" disabled class="tmform-combobox"%s>\n'
    230255                  % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
     256        sSelected = str(sSelected);
    231257        for iValue, sText, _ in aoOptions:
    232258            sValue = str(iValue);
    233259            self._add('            <option value="%s"%s>%s</option>\n'
    234                       % (escapeAttr(sValue), ' selected' if sValue == str(sSelected) else '',
     260                      % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
    235261                         escapeElem(sText)));
    236262        return self._add('          </select>\n'
     
    526552            dSubErrors = self._dErrors[sName];
    527553
    528         for iVar in range(len(aoVariations)):
     554        for iVar, _ in enumerate(aoVariations):
    529555            oVar = copy.copy(aoVariations[iVar]);
    530556            oVar.convertToParamNull();
     
    623649        oDefMember = TestGroupMemberData();
    624650        aoTestGroupMembers = list(aoTestGroupMembers); # Copy it so we can pop.
    625         for iTestCase in range(len(aoAllTestCases)):
     651        for iTestCase, _ in enumerate(aoAllTestCases):
    626652            oTestCase = aoAllTestCases[iTestCase];
    627653
    628654            # Is it a member?
    629655            oMember = None;
    630             for i in range(len(aoTestGroupMembers)):
     656            for i, _ in enumerate(aoTestGroupMembers):
    631657                if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase:
    632658                    oMember = aoTestGroupMembers.pop(i);
     
    735761        oDefMember = SchedGroupMemberData();
    736762        aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop.
    737         for iTestGroup in range(len(aoAllTestGroups)):
     763        for iTestGroup, _ in enumerate(aoAllTestGroups):
    738764            oTestGroup = aoAllTestGroups[iTestGroup];
    739765
    740766            # Is it a member?
    741767            oMember = None;
    742             for i in range(len(aoSchedGroupMembers)):
     768            for i, _ in enumerate(aoSchedGroupMembers):
    743769                if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup:
    744770                    oMember = aoSchedGroupMembers.pop(i);
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py

    r56809 r61217  
    6969    ksActionResultsGroupedByTestCase    = 'ResultsGroupedByTestCase'
    7070    ksActionTestResultDetails           = 'TestResultDetails'
     71    ksActionTestResultFailureDetails    = 'TestResultFailureDetails'
     72    ksActionTestResultFailureAdd        = 'TestResultFailureAdd'
     73    ksActionTestResultFailureAddPost    = 'TestResultFailureAddPost'
     74    ksActionTestResultFailureEdit       = 'TestResultFailureEdit'
     75    ksActionTestResultFailureEditPost   = 'TestResultFailureEditPost'
    7176    ksActionViewLog                     = 'ViewLog'
    7277    ksActionGetFile                     = 'GetFile'
     
    228233                                                                WuiGroupedResultList)
    229234
    230         d[self.ksActionTestResultDetails]          = self.actionTestResultDetails
     235        d[self.ksActionTestResultDetails]          = self._actionTestResultDetails;
     236
     237        d[self.ksActionTestResultFailureAdd]       = self._actionTestResultFailureAdd;
     238        d[self.ksActionTestResultFailureAddPost]   = self._actionTestResultFailureAddPost;
     239        d[self.ksActionTestResultFailureDetails]   = self._actionTestResultFailureDetails;
     240        d[self.ksActionTestResultFailureEdit]      = self._actionTestResultFailureEdit;
     241        d[self.ksActionTestResultFailureEditPost]  = self._actionTestResultFailureEditPost;
    231242
    232243        d[self.ksActionViewLog]                 = self.actionViewLog;
     
    813824        return WuiDispatcherBase._generatePage(self)
    814825
    815     def actionTestResultDetails(self):
     826    def _actionTestResultDetails(self):
    816827        """Show test case execution result details."""
    817828        from testmanager.webui.wuitestresult import WuiTestResult;
     
    849860        return True
    850861
     862    def _actionTestResultFailureAdd(self):
     863        """ Pro forma. """
     864        from testmanager.core.testresults import TestResultFailureLogic, TestResultFailureData;
     865        from testmanager.webui.wuitestresultfailure import WuiTestResultFailure;
     866        return self._actionGenericFormAdd(TestResultFailureData, WuiTestResultFailure);
     867
     868    def _actionTestResultFailureAddPost(self):
     869        """Add test result failure result"""
     870        from testmanager.core.testresults import TestResultFailureLogic, TestResultFailureData;
     871        from testmanager.webui.wuitestresultfailure import WuiTestResultFailure;
     872        if self.ksParamRedirectTo not in self._dParams:
     873            raise WuiException('Missing parameter ' + self.ksParamRedirectTo);
     874
     875        return self._actionGenericFormAddPost(TestResultFailureData, TestResultFailureLogic,
     876                                              WuiTestResultFailure, self.ksActionResultsUnGrouped);
     877
     878    def _actionTestResultFailureDetails(self):
     879        """ Pro forma. """
     880        from testmanager.core.testresults import TestResultFailureLogic, TestResultFailureData;
     881        from testmanager.webui.wuitestresultfailure import WuiTestResultFailure;
     882        return self._actionGenericFormDetails(TestResultFailureData, TestResultFailureLogic,
     883                                              WuiTestResultFailure, 'idTestResult');
     884
     885    def _actionTestResultFailureEdit(self):
     886        """ Pro forma. """
     887        from testmanager.core.testresults import TestResultFailureData;
     888        from testmanager.webui.wuitestresultfailure import WuiTestResultFailure;
     889        return self._actionGenericFormEdit(TestResultFailureData, WuiTestResultFailure,
     890                                           TestResultFailureData.ksParam_idTestResult);
     891
     892    def _actionTestResultFailureEditPost(self):
     893        """Edit test result failure result"""
     894        from testmanager.core.testresults import TestResultFailureLogic, TestResultFailureData;
     895        from testmanager.webui.wuitestresultfailure import WuiTestResultFailure;
     896        if self.ksParamRedirectTo not in self._dParams:
     897            raise WuiException('Missing parameter ' + self.ksParamRedirectTo);
     898
     899        return self._actionGenericFormEditPost(TestResultFailureData, TestResultFailureLogic,
     900                                               WuiTestResultFailure, self.ksActionResultsUnGrouped);
     901
    851902    def actionViewLog(self):
    852903        """
  • trunk/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py

    r56806 r61217  
    3535                                               WuiSvnLink, WuiSvnLinkWithTooltip, WuiBuildLogLink, WuiRawHtml;
    3636from testmanager.webui.wuimain          import WuiMain;
     37from testmanager.webui.wuihlpform       import WuiHlpForm;
     38from testmanager.core.failurereason     import FailureReasonData, FailureReasonLogic;
    3739from testmanager.core.report            import ReportGraphModel;
    3840from testmanager.core.testbox           import TestBoxData;
     
    4042from testmanager.core.testset           import TestSetData;
    4143from testmanager.core.testgroup         import TestGroupData;
     44from testmanager.core.testresults       import TestResultFailureData;
    4245from testmanager.core.build             import BuildData;
    4346from testmanager.core                   import db;
     
    137140            sErrCnt = ' (1 error)' if oTestResult.cErrors == 1 else ' (%d errors)' % oTestResult.cErrors;
    138141
     142        # Format bits for adding or editing the failure reason.  Level 0 is handled at the top of the page.
     143        sChangeReason = '';
     144        if oTestResult.cErrors > 0 and iDepth > 0:
     145            dTmp = {
     146                self._oDisp.ksParamAction: self._oDisp.ksActionTestResultFailureAdd if oTestResult.oReason is None else
     147                                           self._oDisp.ksActionTestResultFailureEdit,
     148                TestResultFailureData.ksParam_idTestResult: oTestResult.idTestResult,
     149            };
     150            sChangeReason = ' <a href="?%s" class="tmtbl-edit-reason" onclick="addRedirectToAnchorHref(this)">%s</a> ' \
     151                          % ( webutils.encodeUrlParams(dTmp), WuiContentBase.ksShortEditLinkHtml );
     152
    139153        # Format the include in graph checkboxes.
    140154        sLineage += ':%u' % (oTestResult.idStrName,);
     
    148162
    149163        if    len(oTestResult.aoChildren) == 0 \
    150           and len(oTestResult.aoValues)   == 0 \
    151           and len(oTestResult.aoMsgs)     == 0 \
    152           and len(oTestResult.aoFiles)    == 0:
     164          and len(oTestResult.aoValues) + len(oTestResult.aoMsgs) + len(oTestResult.aoFiles) == 0:
    153165            # Leaf - single row.
    154166            tsEvent = oTestResult.tsCreated;
     
    160172                     '  <td>%s</td>\n' \
    161173                     '  <td>%s</td>\n' \
    162                      '  <td colspan="2"%s>%s%s</td>\n' \
     174                     '  <td colspan="2"%s>%s%s%s</td>\n' \
    163175                     '  <td>%s</td>\n' \
    164176                     ' </tr>\n' \
     
    170182                       sDisplayName,
    171183                       ' id="failure-%u"' % (iFailure,) if oTestResult.isFailure() else '',
    172                        webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt),
     184                       webutils.escapeElem(oTestResult.enmStatus), webutils.escapeElem(sErrCnt), sChangeReason,
    173185                       sResultGraph );
    174186            iRow += 1;
     
    189201            iRow += 1;
    190202
    191             # Depth.
     203            # Depth. Check if our error count is just reflecting the one of our children.
     204            cErrorsBelow = 0;
    192205            for oChild in oTestResult.aoChildren:
    193206                (sChildHtml, iRow, iFailure) = self._recursivelyGenerateEvents(oChild, sName, sLineage,
    194207                                                                               iRow, iFailure, oTestSet, iDepth + 1);
    195208                sHtml += sChildHtml;
    196 
     209                cErrorsBelow += oChild.cErrors;
     210
     211            if cErrorsBelow >= oTestResult.cErrors:
     212                sChangeReason = '';
    197213
    198214            # Messages.
     
    263279
    264280                sHtml += ' <tr class="%s tmtbl-events-file tmtbl-events-lvl%s">\n' \
    265                          '  <td></td>\n' \
    266                          '  <td>%s</td>\n' \
     281                         '  <td>%s</td>\n' \
     282                         '  <td></td>\n' \
    267283                         '  <td></td>\n' \
    268284                         '  <td>%s</td>\n' \
     
    296312                iRow += 1;
    297313
     314        # Failure reason.
     315        if oTestResult.oReason is not None:
     316            sReasonText = '%s / %s' % (     oTestResult.oReason.oFailureReason.oCategory.sShort,
     317                                            oTestResult.oReason.oFailureReason.sShort, );
     318            sCommentHtml = '';
     319            if oTestResult.oReason.sComment is not None and len(oTestResult.oReason.sComment.strip()) > 0:
     320                sCommentHtml = '<br>' + webutils.escapeElem(oTestResult.oReason.sComment.strip());
     321                sCommentHtml = sCommentHtml.replace('\n', '<br>');
     322
     323            sDetailedReason = ' <a href="?%s" class="tmtbl-show-reason">%s</a>' \
     324                            % ( webutils.encodeUrlParams({ self._oDisp.ksParamAction:
     325                                                           self._oDisp.ksActionTestResultFailureDetails,
     326                                                           TestResultFailureData.ksParam_idTestResult:
     327                                                           oTestResult.idTestResult,}),
     328                                WuiContentBase.ksShortDetailsLinkHtml,);
     329
     330
     331            sHtml += ' <tr class="%s tmtbl-events-reason tmtbl-events-lvl%s">\n' \
     332                     '  <td>%s</td>\n' \
     333                     '  <td colspan="2">%s</td>\n' \
     334                     '  <td colspan="3">%s%s%s%s</td>\n' \
     335                     '  <td>%s</td>\n' \
     336                     ' </tr>\n' \
     337                   % ( 'tmodd' if iRow & 1 else 'tmeven', iDepth,
     338                        webutils.escapeElem(self.formatTsShort(oTestResult.oReason.tsEffective)),
     339                        oTestResult.oReason.oAuthor.sUsername,
     340                        webutils.escapeElem(sReasonText), sDetailedReason, sChangeReason,
     341                        sCommentHtml,
     342                       'todo');
     343            iRow += 1;
     344
    298345        if oTestResult.isFailure():
    299346            iFailure += 1;
    300347
    301348        return (sHtml, iRow, iFailure);
     349
     350
     351    def _generateMainReason(self, oTestResultTree, oTestSet):
     352        """
     353        Generates the form for displaying and updating the main failure reason.
     354
     355        oTestResultTree is an instance TestResultDataEx.
     356        oTestSet is an instance of TestSetData.
     357
     358        """
     359        _ = oTestSet;
     360        sHtml = ' ';
     361
     362        if oTestResultTree.isFailure() or oTestResultTree.cErrors > 0:
     363            sHtml += '   <h2>Failure Reason:</h2>\n';
     364            oData = oTestResultTree.oReason;
     365
     366            # We need the failure reasons for the combobox.
     367            aoFailureReasons = FailureReasonLogic(self._oDisp.getDb()).fetchForCombo('Todo: Figure out why');
     368            assert len(aoFailureReasons) > 0;
     369
     370            # For now we'll use the standard form helper.
     371            sFormActionUrl = '%s?%s=%s' % ( self._oDisp.ksScriptName, self._oDisp.ksParamAction,
     372                                            WuiMain.ksActionTestResultFailureAddPost if oData is None else
     373                                            WuiMain.ksActionTestResultFailureEditPost )
     374            oForm = WuiHlpForm('failure-reason', sFormActionUrl,
     375                               sOnSubmit = WuiHlpForm.ksOnSubmit_AddReturnToFieldWithCurrentUrl);
     376            oForm.addTextHidden(TestResultFailureData.ksParam_idTestResult, oTestResultTree.idTestResult);
     377            oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, oData.idFailureReason if oData is not None else -1,
     378                              'Reason', aoFailureReasons);
     379            oForm.addMultilineText(TestResultFailureData.ksParam_sComment,
     380                                   oData.sComment if oData is not None else '', 'Comment');
     381            if oData is not None:
     382                oForm.addNonText('%s (%s)' % (oData.oAuthor.sUsername, oData.oAuthor.sUsername), 'Sheriff');
     383                oForm.addNonText(oData.tsEffective, 'When');
     384                oForm.addTextHidden(TestResultFailureData.ksParam_tsEffective, oData.tsEffective);
     385                oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, oData.tsExpire);
     386                oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, oData.uidAuthor);
     387            else:
     388                oForm.addTextHidden(TestResultFailureData.ksParam_tsEffective, '');
     389                oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, '');
     390                oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, '');
     391
     392            oForm.addSubmit('Change Reason', );
     393            sHtml += oForm.finalize();
     394        return sHtml;
     395
    302396
    303397    def showTestCaseResultDetails(self,             # pylint: disable=R0914,R0915
     
    534628
    535629        sHtml += '  <td valign="top" width="80%" style="padding-left:6px">\n';
     630        sHtml += self._generateMainReason(oTestResultTree, oTestSet);
     631
    536632        sHtml += '   <h2>Events:</h2>\n';
    537633        sHtml += '   <form action="#" method="get" id="graph-form">\n' \
     
    614710            'Start',
    615711            'Product Build',
    616             'Validation Kit',
    617             'TestBox OS',
    618             'TestBox Name',
     712            'Kit',
     713            'Box',
     714            'OS.Arch',
    619715            'Test Case',
    620716            'Elapsed',
    621717            'Result',
     718            'Reason',
    622719        ];
    623720        self._asColumnAttribs = ['align="center"', 'align="center"', 'align="center"',
    624721                                 'align="center"', 'align="center"', 'align="center"',
    625722                                 'align="center"', 'align="center"', 'align="center"',
    626                                  'align="center"', 'align="center"', 'align="center"' ]
     723                                 'align="center"', 'align="center"', 'align="center"',
     724                                 'align="center"', ];
    627725
    628726
     
    650748        oValidationKit = None;
    651749        if oEntry.idBuildTestSuite is not None:
    652             oValidationKit = WuiTmLink('#%d - r%s' % (oEntry.idBuildTestSuite, oEntry.iRevisionTestSuite),
     750            oValidationKit = WuiTmLink('r%s' % (oEntry.iRevisionTestSuite,),
    653751                                   WuiAdmin.ksScriptName,
    654752                                   { WuiAdmin.ksParamAction:  WuiAdmin.ksActionBuildDetails,
     
    656754                                   fBracketed = False);
    657755
    658 
    659         aoTestSetLinks = [ WuiTmLink(oEntry.enmStatus,
    660                                      WuiMain.ksScriptName,
    661                                      { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
    662                                        TestSetData.ksParam_idTestSet: oEntry.idTestSet },
    663                                      fBracketed = False),];
     756        aoTestSetLinks = [];
     757        aoTestSetLinks.append(WuiTmLink(oEntry.enmStatus,
     758                                        WuiMain.ksScriptName,
     759                                        { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
     760                                          TestSetData.ksParam_idTestSet: oEntry.idTestSet },
     761                                        fBracketed = False));
    664762        if oEntry.cErrors > 0:
    665             aoTestSetLinks.append(WuiTmLink('- %d error(s)' % (oEntry.cErrors, ),
     763            aoTestSetLinks.append(WuiRawHtml('-'));
     764            aoTestSetLinks.append(WuiTmLink('%d error%s' % (oEntry.cErrors, '' if oEntry.cErrors == 1 else 's', ),
    666765                                            WuiMain.ksScriptName,
    667766                                            { WuiMain.ksParamAction: WuiMain.ksActionTestResultDetails,
     
    688787        sTestBoxTitle += u'CPU features:\t' + u', '.join(asFeatures);
    689788
     789        # Reason:
     790        oReason = None;
     791        if oEntry.oFailureReason is not None:
     792            sReasonTitle  = 'Reason:  \t%s\n' % ( oEntry.oFailureReason.sShort, );
     793            sReasonTitle += 'Category:\t%s\n' % ( oEntry.oFailureReason.oCategory.sShort, );
     794            sReasonTitle += 'Assigned:\t%s\n' % ( self.formatTsShort(oEntry.tsFailureReasonAssigned), );
     795            sReasonTitle += 'By User: \t%s\n' % ( oEntry.oFailureReasonAssigner.sUsername, );
     796            if oEntry.sFailureReasonComment is not None and len(oEntry.sFailureReasonComment) > 0:
     797                sReasonTitle += 'Comment: \t%s\n' % ( self.formatTsShort(oEntry.sFailureReasonComment), );
     798            if oEntry.oFailureReason.iTicket is not None and oEntry.oFailureReason.iTicket > 0:
     799                sReasonTitle += 'xTracker:\t#%s\n' % ( oEntry.oFailureReason.iTicket, );
     800            for i, sUrl in enumerate(oEntry.oFailureReason.asUrls):
     801                sUrl = sUrl.strip();
     802                if len(sUrl) > 0:
     803                    sReasonTitle += 'URL#%u:  \t%s\n' % ( i, sUrl, );
     804            oReason = WuiTmLink(oEntry.oFailureReason.sShort, WuiAdmin.ksScriptName,
     805                                { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonDetails,
     806                                  FailureReasonData.ksParam_idFailureReason: oEntry.oFailureReason.idFailureReason },
     807                                sTitle = sReasonTitle);
     808
    690809        return [
    691810            oEntry.tsCreated,
    692             [ WuiTmLink('#%d - %s %s (%s)' % (oEntry.idBuild, oEntry.sProduct, oEntry.sVersion, oEntry.sType,),
     811            [ WuiTmLink('%s %s (%s)' % (oEntry.sProduct, oEntry.sVersion, oEntry.sType,),
    693812                        WuiMain.ksScriptName, self._dRevLinkParams, sTitle = '%s' % (oEntry.sBranch,), fBracketed = False),
    694813              WuiSvnLinkWithTooltip(oEntry.iRevision, 'vbox'), ## @todo add sRepository TestResultListingData
     
    699818              ],
    700819            oValidationKit,
    701             '%s.%s' % (oEntry.sOs, oEntry.sArch),
    702820            [ WuiTmLink(oEntry.sTestBoxName, WuiMain.ksScriptName, self._dTestBoxLinkParams, fBracketed = False,
    703821                        sTitle = sTestBoxTitle),
     
    706824                          TestBoxData.ksParam_idTestBox: oEntry.idTestBox },
    707825                        fBracketed = False) ],
     826            '%s.%s' % (oEntry.sOs, oEntry.sArch),
    708827            [ WuiTmLink(oEntry.sTestCaseName, WuiMain.ksScriptName, self._dTestCaseLinkParams, fBracketed = False,
    709828                        sTitle = (oEntry.sBaseCmd + ' ' + oEntry.sArgs) if oEntry.sArgs else oEntry.sBaseCmd),
     
    713832                        fBracketed = False), ],
    714833            oEntry.tsElapsed,
    715             aoTestSetLinks
     834            aoTestSetLinks,
     835            oReason
    716836        ];
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette