- Timestamp:
- May 27, 2016 6:00:16 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107541
- Location:
- trunk/src/VBox/ValidationKit/testmanager
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testmanager/core/failurecategory.py
r61220 r61250 31 31 32 32 # Validation Kit imports. 33 from testmanager.core.base import ModelDataBase, ModelLogicBase, TMRowInUse, TMInvalidData, TMRowNotFound; 33 from testmanager.core.base import ModelDataBase, ModelLogicBase, TMRowInUse, TMInvalidData, TMRowNotFound, \ 34 ChangeLogEntry, AttributeChangeEntry; 35 from testmanager.core.useraccount import UserAccountLogic; 34 36 35 37 … … 137 139 aoRows.append(FailureCategoryData().initFromDbRow(aoRow)) 138 140 return aoRows 141 142 143 def fetchForChangeLog(self, idFailureCategory, iStart, cMaxRows, tsNow): # pylint: disable=R0914 144 """ 145 Fetches change log entries for a failure reason. 146 147 Returns an array of ChangeLogEntry instance and an indicator whether 148 there are more entries. 149 Raises exception on error. 150 """ 151 if tsNow is None: 152 tsNow = self._oDb.getCurrentTimestamp(); 153 154 # 1. Get a list of the relevant changes. 155 self._oDb.execute('SELECT * FROM FailureCategories WHERE idFailureCategory = %s AND tsEffective <= %s\n' 156 'ORDER BY tsEffective DESC\n' 157 'LIMIT %s OFFSET %s\n' 158 , ( idFailureCategory, tsNow, cMaxRows + 1, iStart, )); 159 aoRows = []; 160 for aoChange in self._oDb.fetchAll(): 161 aoRows.append(FailureCategoryData().initFromDbRow(aoChange)); 162 163 # 2. Calculate the changes. 164 aoEntries = []; 165 for i in xrange(0, len(aoRows) - 1): 166 oNew = aoRows[i]; 167 oOld = aoRows[i + 1]; 168 169 aoChanges = []; 170 for sAttr in oNew.getDataAttributes(): 171 if sAttr not in [ 'tsEffective', 'tsExpire', 'uidAuthor', ]: 172 oOldAttr = getattr(oOld, sAttr); 173 oNewAttr = getattr(oNew, sAttr); 174 if oOldAttr != oNewAttr: 175 aoChanges.append(AttributeChangeEntry(sAttr, oNewAttr, oOldAttr, str(oNewAttr), str(oOldAttr))); 176 177 aoEntries.append(ChangeLogEntry(oNew.uidAuthor, None, oNew.tsEffective, oNew.tsExpire, oNew, oOld, aoChanges)); 178 179 # If we're at the end of the log, add the initial entry. 180 if len(aoRows) <= cMaxRows and len(aoRows) > 0: 181 oNew = aoRows[-1]; 182 aoEntries.append(ChangeLogEntry(oNew.uidAuthor, None, oNew.tsEffective, oNew.tsExpire, oNew, None, [])); 183 184 return (UserAccountLogic(self._oDb).resolveChangeLogAuthors(aoEntries), len(aoRows) > cMaxRows); 185 139 186 140 187 def getFailureCategoriesForCombo(self, tsEffective = None): -
trunk/src/VBox/ValidationKit/testmanager/core/failurereason.py
r61220 r61250 31 31 32 32 # Validation Kit imports. 33 from testmanager.core.base import ModelDataBase, ModelLogicBase, TMRowNotFound, TMInvalidData, TMRowInUse; 33 from testmanager.core.base import ModelDataBase, ModelLogicBase, TMRowNotFound, TMInvalidData, TMRowInUse, \ 34 AttributeChangeEntry, ChangeLogEntry; 34 35 from testmanager.core.useraccount import UserAccountLogic; 35 36 … … 151 152 Fetches Failure Category records. 152 153 153 Returns an array (list) of FailureReasonData items, empty list if none.154 Returns an array (list) of FailureReasonDataEx items, empty list if none. 154 155 Raises exception on error. 155 156 """ 157 self._ensureCachesPresent(); 158 159 if tsNow is None: 160 self._oDb.execute('SELECT FailureReasons.*,\n' 161 ' FailureCategories.sShort AS sCategory\n' 162 'FROM FailureReasons,\n' 163 ' FailureCategories\n' 164 'WHERE FailureReasons.tsExpire = \'infinity\'::TIMESTAMP\n' 165 ' AND FailureCategories.idFailureCategory = FailureReasons.idFailureCategory\n' 166 ' AND FailureCategories.tsExpire = \'infinity\'::TIMESTAMP\n' 167 'ORDER BY sCategory ASC, sShort ASC\n' 168 'LIMIT %s OFFSET %s\n' 169 , (cMaxRows, iStart,)); 170 else: 171 self._oDb.execute('SELECT FailureReasons.*,\n' 172 ' FailureCategories.sShort AS sCategory\n' 173 'FROM FailureReasons,\n' 174 ' FailureCategories\n' 175 'WHERE FailureReasons.tsExpire > %s\n' 176 ' AND FailureReasons.tsEffective <= %s\n' 177 ' AND FailureCategories.idFailureCategory = FailureReasons.idFailureCategory\n' 178 ' AND FailureReasons.tsExpire > %s\n' 179 ' AND FailureReasons.tsEffective <= %s\n' 180 'ORDER BY sCategory ASC, sShort ASC\n' 181 'LIMIT %s OFFSET %s\n' 182 , (tsNow, tsNow, tsNow, tsNow, cMaxRows, iStart,)); 183 184 aoRows = [] 185 for aoRow in self._oDb.fetchAll(): 186 aoRows.append(FailureReasonDataEx().initFromDbRowEx(aoRow, self.oCategoryLogic, self.oUserAccountLogic)); 187 return aoRows 188 189 def fetchForListingInCategory(self, iStart, cMaxRows, tsNow, idFailureCategory): 190 """ 191 Fetches Failure Category records. 192 193 Returns an array (list) of FailureReasonDataEx items, empty list if none. 194 Raises exception on error. 195 """ 196 self._ensureCachesPresent(); 156 197 157 198 if tsNow is None: 158 199 self._oDb.execute('SELECT *\n' 159 200 'FROM FailureReasons\n' 160 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n' 161 'ORDER BY idFailureReason DESC\n' 201 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n' 202 ' AND idFailureCategory = %s\n' 203 'ORDER BY sShort ASC\n' 162 204 'LIMIT %s OFFSET %s\n' 163 , ( cMaxRows, iStart,));205 , ( idFailureCategory, cMaxRows, iStart,)); 164 206 else: 165 207 self._oDb.execute('SELECT *\n' 166 208 'FROM FailureReasons\n' 167 'WHERE tsExpire > %s\n' 168 ' AND tsEffective <= %s\n' 169 'ORDER BY idFailureReason DESC\n' 209 'WHERE idFailureCategory = %s\n' 210 ' AND tsExpire > %s\n' 211 ' AND tsEffective <= %s\n' 212 'ORDER BY sShort ASC\n' 170 213 'LIMIT %s OFFSET %s\n' 171 , ( tsNow, tsNow, cMaxRows, iStart,));214 , ( tsNow, tsNow, idFailureCategory, cMaxRows, iStart,)); 172 215 173 216 aoRows = [] 174 217 for aoRow in self._oDb.fetchAll(): 175 aoRows.append(FailureReasonData ().initFromDbRow(aoRow))218 aoRows.append(FailureReasonDataEx().initFromDbRowEx(aoRow, self.oCategoryLogic, self.oUserAccountLogic)); 176 219 return aoRows 177 220 … … 204 247 return [(-1, sFirstEntry, '')] + aoRows; 205 248 249 250 def fetchForChangeLog(self, idFailureReason, iStart, cMaxRows, tsNow): # pylint: disable=R0914 251 """ 252 Fetches change log entries for a failure reason. 253 254 Returns an array of ChangeLogEntry instance and an indicator whether 255 there are more entries. 256 Raises exception on error. 257 """ 258 self._ensureCachesPresent(); 259 260 if tsNow is None: 261 tsNow = self._oDb.getCurrentTimestamp(); 262 263 # 1. Get a list of the relevant changes. 264 self._oDb.execute('SELECT * FROM FailureReasons WHERE idFailureReason = %s AND tsEffective <= %s\n' 265 'ORDER BY tsEffective DESC\n' 266 'LIMIT %s OFFSET %s\n' 267 , ( idFailureReason, tsNow, cMaxRows + 1, iStart, )); 268 aoRows = []; 269 for aoChange in self._oDb.fetchAll(): 270 aoRows.append(FailureReasonData().initFromDbRow(aoChange)); 271 272 # 2. Calculate the changes. 273 aoEntries = []; 274 for i in xrange(0, len(aoRows) - 1): 275 oNew = aoRows[i]; 276 oOld = aoRows[i + 1]; 277 278 aoChanges = []; 279 for sAttr in oNew.getDataAttributes(): 280 if sAttr not in [ 'tsEffective', 'tsExpire', 'uidAuthor', ]: 281 oOldAttr = getattr(oOld, sAttr); 282 oNewAttr = getattr(oNew, sAttr); 283 if oOldAttr != oNewAttr: 284 if sAttr == 'idFailureCategory': 285 oCat = self.oCategoryLogic.cachedLookup(oOldAttr); 286 if oCat is not None: 287 oOldAttr = '%s (%s)' % (oOldAttr, oCat.sShort, ); 288 oCat = self.oCategoryLogic.cachedLookup(oNewAttr); 289 if oCat is not None: 290 oNewAttr = '%s (%s)' % (oNewAttr, oCat.sShort, ); 291 aoChanges.append(AttributeChangeEntry(sAttr, oNewAttr, oOldAttr, str(oNewAttr), str(oOldAttr))); 292 293 aoEntries.append(ChangeLogEntry(oNew.uidAuthor, None, oNew.tsEffective, oNew.tsExpire, oNew, oOld, aoChanges)); 294 295 # If we're at the end of the log, add the initial entry. 296 if len(aoRows) <= cMaxRows and len(aoRows) > 0: 297 oNew = aoRows[-1]; 298 aoEntries.append(ChangeLogEntry(oNew.uidAuthor, None, oNew.tsEffective, oNew.tsExpire, oNew, None, [])); 299 300 return (UserAccountLogic(self._oDb).resolveChangeLogAuthors(aoEntries), len(aoRows) > cMaxRows); 301 302 206 303 def getById(self, idFailureReason): 207 304 """Get Failure Reason data by idFailureReason""" … … 333 430 334 431 if self._oDb.getRowCount() == 1: 335 if self.oCategoryLogic is None: 336 from testmanager.core.failurecategory import FailureCategoryLogic; 337 self.oCategoryLogic = FailureCategoryLogic(self._oDb); 338 if self.oUserAccountLogic is None: 339 self.oUserAccountLogic = UserAccountLogic(self._oDb); 432 self._ensureCachesPresent(); 340 433 oEntry = FailureReasonDataEx().initFromDbRowEx(self._oDb.fetchOne(), self.oCategoryLogic, 341 434 self.oUserAccountLogic); … … 386 479 return True; 387 480 481 482 def _ensureCachesPresent(self): 483 """ Ensures we've got the cache references resolved. """ 484 if self.oCategoryLogic is None: 485 from testmanager.core.failurecategory import FailureCategoryLogic; 486 self.oCategoryLogic = FailureCategoryLogic(self._oDb); 487 if self.oUserAccountLogic is None: 488 self.oUserAccountLogic = UserAccountLogic(self._oDb); 489 return True; 490 491 -
trunk/src/VBox/ValidationKit/testmanager/core/testresults.py
r61220 r61250 38 38 from testmanager import config; 39 39 from testmanager.core.base import ModelDataBase, ModelLogicBase, ModelDataBaseTestCase, TMExceptionBase, \ 40 TMTooManyRows, TMInvalidData, TMRowNotFound, TMRowAlreadyExists; 40 TMTooManyRows, TMInvalidData, TMRowNotFound, TMRowAlreadyExists, \ 41 ChangeLogEntry, AttributeChangeEntry; 41 42 from testmanager.core.testgroup import TestGroupData; 42 43 from testmanager.core.build import BuildDataEx; 43 from testmanager.core.failurereason import FailureReasonLogic ;44 from testmanager.core.failurereason import FailureReasonLogic, FailureReasonData; 44 45 from testmanager.core.testbox import TestBoxData; 45 46 from testmanager.core.testcase import TestCaseData; … … 126 127 return self; 127 128 129 def initFromDbWithId(self, oDb, idTestResult, tsNow = None, sPeriodBack = None): 130 """ 131 Initialize from the database, given the ID of a row. 132 """ 133 _ = tsNow; 134 _ = sPeriodBack; 135 oDb.execute('SELECT *\n' 136 'FROM TestResults\n' 137 'WHERE idTestResult = %s\n' 138 , ( idTestResult,)); 139 aoRow = oDb.fetchOne() 140 if aoRow is None: 141 raise TMRowNotFound('idTestResult=%s not found' % (idTestResult,)); 142 return self.initFromDbRow(aoRow); 143 128 144 def isFailure(self): 129 145 """ Check if it's a real failure. """ … … 430 446 kasAllowNullAttributes = ['tsEffective', 'tsExpire', 'uidAuthor', 'sComment' ]; 431 447 448 kcDbColumns = 6; 449 432 450 def __init__(self): 433 451 ModelDataBase.__init__(self) … … 467 485 if aoRow is None: 468 486 raise TMRowNotFound('idTestResult=%s not found (tsNow=%s, sPeriodBack=%s)' % (idTestResult, tsNow, sPeriodBack)); 487 assert len(aoRow) == self.kcDbColumns; 469 488 return self.initFromDbRow(aoRow); 470 489 … … 1922 1941 ModelLogicBase.__init__(self, oDb) 1923 1942 1943 def fetchForChangeLog(self, idTestResult, iStart, cMaxRows, tsNow): # pylint: disable=R0914 1944 """ 1945 Fetches change log entries for a failure reason. 1946 1947 Returns an array of ChangeLogEntry instance and an indicator whether 1948 there are more entries. 1949 Raises exception on error. 1950 """ 1951 1952 if tsNow is None: 1953 tsNow = self._oDb.getCurrentTimestamp(); 1954 1955 # 1. Get a list of the changes from both TestResultFailures and assoicated 1956 # FailureReasons. The latter is useful since the failure reason 1957 # description may evolve along side the invidiual failure analysis. 1958 self._oDb.execute('( SELECT trf.tsEffective AS tsEffectiveChangeLog,\n' 1959 ' trf.uidAuthor AS uidAuthorChangeLog,\n' 1960 ' trf.*,\n' 1961 ' fr.*\n' 1962 ' FROM TestResultFailures trf,\n' 1963 ' FailureReasons fr\n' 1964 ' WHERE trf.idTestResult = %s\n' 1965 ' AND trf.tsEffective <= %s\n' 1966 ' AND trf.idFailureReason = fr.idFailureReason\n' 1967 ' AND fr.tsEffective <= trf.tsEffective\n' 1968 ' AND fr.tsExpire > trf.tsEffective\n' 1969 ')\n' 1970 'UNION\n' 1971 '( SELECT fr.tsEffective AS tsEffectiveChangeLog,\n' 1972 ' fr.uidAuthor AS uidAuthorChangeLog,\n' 1973 ' trf.*,\n' 1974 ' fr.*\n' 1975 ' FROM TestResultFailures trf,\n' 1976 ' FailureReasons fr\n' 1977 ' WHERE trf.idTestResult = %s\n' 1978 ' AND trf.tsEffective <= %s\n' 1979 ' AND trf.idFailureReason = fr.idFailureReason\n' 1980 ' AND fr.tsEffective > trf.tsEffective\n' 1981 ' AND fr.tsEffective < trf.tsExpire\n' 1982 ')\n' 1983 'ORDER BY tsEffectiveChangeLog DESC\n' 1984 'LIMIT %s OFFSET %s\n' 1985 , ( idTestResult, tsNow, idTestResult, tsNow, cMaxRows + 1, iStart, )); 1986 1987 aaoRows = []; 1988 for aoChange in self._oDb.fetchAll(): 1989 oTrf = TestResultFailureDataEx().initFromDbRow(aoChange[2:]); 1990 oFr = FailureReasonData().initFromDbRow(aoChange[(2+TestResultFailureData.kcDbColumns):]); 1991 oTrf.oFailureReason = oFr; 1992 aaoRows.append([aoChange[0], aoChange[1], oTrf, oFr]); 1993 1994 # 2. Calculate the changes. 1995 oFailureCategoryLogic = None; 1996 aoEntries = []; 1997 for i in xrange(0, len(aaoRows) - 1): 1998 aoNew = aaoRows[i]; 1999 aoOld = aaoRows[i + 1]; 2000 2001 aoChanges = []; 2002 oNew = aoNew[2]; 2003 oOld = aoOld[2]; 2004 for sAttr in oNew.getDataAttributes(): 2005 if sAttr not in [ 'tsEffective', 'tsExpire', 'uidAuthor', 'oFailureReason', 'oAuthor' ]: 2006 oOldAttr = getattr(oOld, sAttr); 2007 oNewAttr = getattr(oNew, sAttr); 2008 if oOldAttr != oNewAttr: 2009 if sAttr == 'idFailureReason': 2010 oNewAttr = '%s (%s)' % (oNewAttr, oNew.oFailureReason.sShort, ); 2011 oOldAttr = '%s (%s)' % (oOldAttr, oOld.oFailureReason.sShort, ); 2012 aoChanges.append(AttributeChangeEntry(sAttr, oNewAttr, oOldAttr, str(oNewAttr), str(oOldAttr))); 2013 if oOld.idFailureReason == oNew.idFailureReason: 2014 oNew = aoNew[3]; 2015 oOld = aoOld[3]; 2016 for sAttr in oNew.getDataAttributes(): 2017 if sAttr not in [ 'tsEffective', 'tsExpire', 'uidAuthor', ]: 2018 oOldAttr = getattr(oOld, sAttr); 2019 oNewAttr = getattr(oNew, sAttr); 2020 if oOldAttr != oNewAttr: 2021 if sAttr == 'idFailureCategory': 2022 if oFailureCategoryLogic is None: 2023 from testmanager.core.failurecategory import FailureCategoryLogic; 2024 oFailureCategoryLogic = FailureCategoryLogic(self._oDb); 2025 oCat = oFailureCategoryLogic.cachedLookup(oNewAttr); 2026 if oCat is not None: 2027 oNewAttr = '%s (%s)' % (oNewAttr, oCat.sShort, ); 2028 oCat = oFailureCategoryLogic.cachedLookup(oOldAttr); 2029 if oCat is not None: 2030 oOldAttr = '%s (%s)' % (oOldAttr, oCat.sShort, ); 2031 aoChanges.append(AttributeChangeEntry(sAttr, oNewAttr, oOldAttr, str(oNewAttr), str(oOldAttr))); 2032 2033 2034 tsExpire = aaoRows[i - 1][0] if i > 0 else aoNew[2].tsExpire; 2035 aoEntries.append(ChangeLogEntry(aoNew[1], None, aoNew[0], tsExpire, aoNew[2], aoOld[2], aoChanges)); 2036 2037 # If we're at the end of the log, add the initial entry. 2038 if len(aaoRows) <= cMaxRows and len(aaoRows) > 0: 2039 aoNew = aaoRows[-1]; 2040 tsExpire = aaoRows[-1 - 1][0] if len(aaoRows) > 1 else aoNew[2].tsExpire; 2041 aoEntries.append(ChangeLogEntry(aoNew[1], None, aoNew[0], tsExpire, aoNew[2], None, [])); 2042 2043 return (UserAccountLogic(self._oDb).resolveChangeLogAuthors(aoEntries), len(aaoRows) > cMaxRows); 2044 2045 1924 2046 def getById(self, idTestResult): 1925 2047 """Get Test result failure reason data by idTestResult""" -
trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurecategory.py
r61240 r61250 31 31 32 32 # Validation Kit imports. 33 from testmanager.webui.wuicontentbase import WuiFormContentBase, WuiListContentBase, WuiTmLink 34 from testmanager.core.failurecategory import FailureCategoryData 33 from testmanager.webui.wuicontentbase import WuiFormContentBase, WuiContentBase, WuiListContentBase, WuiTmLink; 34 from testmanager.webui.wuiadminfailurereason import WuiAdminFailureReasonList; 35 from testmanager.core.failurecategory import FailureCategoryData; 36 from testmanager.core.failurereason import FailureReasonLogic; 37 38 39 class WuiFailureReasonCategoryLink(WuiTmLink): 40 """ Link to a failure category. """ 41 def __init__(self, idFailureCategory, sName = WuiContentBase.ksShortDetailsLink, sTitle = None, fBracketed = None): 42 if fBracketed is None: 43 fBracketed = len(sName) > 2; 44 from testmanager.webui.wuiadmin import WuiAdmin; 45 WuiTmLink.__init__(self, sName = sName, 46 sUrlBase = WuiAdmin.ksScriptName, 47 dParams = { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureCategoryDetails, 48 FailureCategoryData.ksParam_idFailureCategory: idFailureCategory, }, 49 fBracketed = fBracketed); 50 self.idFailureCategory = idFailureCategory; 51 35 52 36 53 … … 71 88 return True; 72 89 90 def _generatePostFormContent(self, oData): 91 """ 92 Adds a table with the category members below the form. 93 """ 94 if oData.idFailureCategory is not None and oData.idFailureCategory >= 0: 95 oLogic = FailureReasonLogic(self._oDisp.getDb()); 96 tsNow = self._oDisp.getNow(); 97 cMax = 4096; 98 aoEntries = oLogic.fetchForListingInCategory(0, cMax, tsNow, oData.idFailureCategory) 99 if len(aoEntries) > 0: 100 oList = WuiAdminFailureReasonList(aoEntries, 0, cMax, tsNow, fnDPrint = None, oDisp = self._oDisp); 101 return [ [ 'Members', oList.show(fShowNavigation = False)[1]], ]; 102 return []; 103 104 73 105 74 106 class WuiFailureCategoryList(WuiListContentBase): -
trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminfailurereason.py
r61220 r61250 32 32 # Validation Kit imports. 33 33 from testmanager.webui.wuibase import WuiException 34 from testmanager.webui.wuicontentbase import WuiFormContentBase, WuiListContentBase, WuiTmLink 35 from testmanager.core.failurereason import FailureReasonData 36 from testmanager.core.failurecategory import FailureCategoryLogic 37 from testmanager.core.db import TMDatabaseConnection 34 from testmanager.webui.wuicontentbase import WuiFormContentBase, WuiListContentBase, WuiContentBase, WuiTmLink; 35 from testmanager.core.failurereason import FailureReasonData; 36 from testmanager.core.failurecategory import FailureCategoryLogic; 37 from testmanager.core.db import TMDatabaseConnection; 38 39 40 41 class WuiFailureReasonDetailsLink(WuiTmLink): 42 """ Short link to a failure reason. """ 43 def __init__(self, idFailureReason, sName = WuiContentBase.ksShortDetailsLink, sTitle = None, fBracketed = None): 44 if fBracketed is None: 45 fBracketed = len(sName) > 2; 46 from testmanager.webui.wuiadmin import WuiAdmin; 47 WuiTmLink.__init__(self, sName = sName, 48 sUrlBase = WuiAdmin.ksScriptName, 49 dParams = { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonDetails, 50 FailureReasonData.ksParam_idFailureReason: idFailureReason, }, 51 fBracketed = fBracketed); 52 self.idFailureReason = idFailureReason; 53 54 55 56 class WuiFailureReasonAddLink(WuiTmLink): 57 """ Link for adding a failure reason. """ 58 def __init__(self, sName = WuiContentBase.ksShortAddLink, sTitle = None, fBracketed = None): 59 if fBracketed is None: 60 fBracketed = len(sName) > 2; 61 from testmanager.webui.wuiadmin import WuiAdmin; 62 WuiTmLink.__init__(self, sName = sName, 63 sUrlBase = WuiAdmin.ksScriptName, 64 dParams = { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonAdd, }, 65 fBracketed = fBracketed); 66 38 67 39 68 … … 107 136 108 137 def _formatListEntry(self, iEntry): 109 from testmanager.webui.wuiadmin import WuiAdmin 138 from testmanager.webui.wuiadmin import WuiAdmin 139 from testmanager.webui.wuiadminfailurecategory import WuiFailureReasonCategoryLink; 110 140 oEntry = self._aoEntries[iEntry] 111 141 112 142 return [ oEntry.idFailureReason, 113 oEntry.idFailureCategory,143 WuiFailureReasonCategoryLink(oEntry.idFailureCategory, sName = oEntry.oCategory.sShort, fBracketed = False), 114 144 oEntry.sShort, 115 145 oEntry.sFull, -
trunk/src/VBox/ValidationKit/testmanager/webui/wuibase.py
r61239 r61250 104 104 self._oSrvGlue = oSrvGlue; 105 105 self._oDb = TMDatabaseConnection(self.dprint if config.g_kfWebUiSqlDebug else None, oSrvGlue = oSrvGlue); 106 self._tsNow = None; # Set by getEffectiveDateParam. 106 107 self._asCheckedParams = []; 107 108 self._dParams = None; # Set by dispatchRequest. … … 303 304 return self._oDb; 304 305 306 def getNow(self): 307 """ 308 Returns the effective date. 309 """ 310 return self._tsNow; 311 305 312 306 313 # … … 506 513 return aoListOfTestCases 507 514 508 def getEffectiveDateParam(self, sParamName =None):515 def getEffectiveDateParam(self, sParamName = None): 509 516 """ 510 517 Gets the effective date parameter. 518 511 519 Returns a timestamp suitable for database and url parameters. 512 520 Returns None if not found or empty. 521 522 The first call with sParamName set to None will set the internal _tsNow 523 value upon successfull return. 513 524 """ 514 525 … … 535 546 if sError is not None: 536 547 raise WuiException('%s parameter "%s" ("%s") is invalid: %s' % (self._sAction, sName, sValue, sError)); 548 if sParamName is None and self._tsNow is None: 549 self._tsNow = sValue; 537 550 return sValue; 538 551 … … 555 568 oDate = self._oDb.fetchOne()[0]; 556 569 557 return str(oDate); 570 sValue = str(oDate); 571 if sParamName is None and self._tsNow is None: 572 self._tsNow = sValue; 573 return sValue; 558 574 559 575 def getRedirectToParameter(self, sDefault = None): -
trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py
r61223 r61250 345 345 _ = oForm; _ = oData; 346 346 raise Exception('Reimplement me!'); 347 348 def _generatePostFormContent(self, oData): 349 """ 350 Generate optional content that comes below the form. 351 Returns a list of tuples, where the first tuple element is the title 352 and the second the content. I.e. similar to show() output. 353 """ 354 _ = oData; 355 return []; 347 356 348 357 def _calcChangeLogEntryLinks(self, aoEntries, iEntry): … … 522 531 return sContent; 523 532 533 def _generateTopRowFormActions(self, oData): 534 """ 535 Returns a list of WuiTmLinks. 536 """ 537 aoActions = []; 538 if self._sMode == self.ksMode_Show and self._fEditable: 539 # Remove _idGen and effective date since we're always editing the current data, 540 # and make sure the primary ID is present. 541 dParams = self._oDisp.getParameters(); 542 if hasattr(oData, 'ksIdGenAttr'): 543 sIdGenParam = getattr(oData, 'ksParam_' + oData.ksIdGenAttr); 544 if sIdGenParam in dParams: 545 del dParams[sIdGenParam]; 546 if WuiDispatcherBase.ksParamEffectiveDate in dParams: 547 del dParams[WuiDispatcherBase.ksParamEffectiveDate]; 548 dParams[getattr(oData, 'ksParam_' + oData.ksIdAttr)] = getattr(oData, oData.ksIdAttr); 549 550 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Edit'); 551 aoActions.append(WuiTmLink('Edit', '', dParams)); 552 553 # Add clone operation if available. This uses the same data selection as for showing details. 554 if hasattr(self._oDisp, self._sActionBase + 'Clone'): 555 dParams = self._oDisp.getParameters(); 556 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Clone'); 557 aoActions.append(WuiTmLink('Clone', '', dParams)); 558 559 elif self._sMode == self.ksMode_Edit: 560 # Details views the details at a given time, so we need either idGen or an effecive date + regular id. 561 dParams = {}; 562 if hasattr(oData, 'ksIdGenAttr'): 563 sIdGenParam = getattr(oData, 'ksParam_' + oData.ksIdGenAttr); 564 dParams[sIdGenParam] = getattr(oData, oData.ksIdGenAttr); 565 elif hasattr(oData, 'tsEffective'): 566 dParams[WuiDispatcherBase.ksParamEffectiveDate] = oData.tsEffective; 567 dParams[getattr(oData, 'ksParam_' + oData.ksIdAttr)] = getattr(oData, oData.ksIdAttr); 568 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Details'); 569 aoActions.append(WuiTmLink('Details', '', dParams)); 570 571 return aoActions; 572 524 573 def showForm(self, dErrors = None, sErrorMsg = None): 525 574 """ … … 544 593 sContent = oForm.finalize(); 545 594 595 # Add any post form content. 596 atPostFormContent = self._generatePostFormContent(self._oData); 597 if atPostFormContent is not None and len(atPostFormContent) > 0: 598 for iSection, tSection in enumerate(atPostFormContent): 599 (sSectionTitle, sSectionContent) = tSection; 600 sContent += u'<div id="postform-%d" class="tmformpostsection">\n' % (iSection,); 601 if sSectionTitle is not None and len(sSectionTitle) > 0: 602 sContent += '<h3 class="tmformpostheader">%s</h3>\n' % (webutils.escapeElem(sSectionTitle),); 603 sContent += u' <div id="postform-%d-content" class="tmformpostcontent">\n' % (iSection,); 604 sContent += sSectionContent; 605 sContent += u' </div>\n' \ 606 u'</div>\n'; 607 546 608 # Add action to the top. 547 aoActions = []; 548 if self._sMode == self.ksMode_Show and self._fEditable: 549 # Remove _idGen and effective date since we're always editing the current data, 550 # and make sure the primary ID is present. 551 dParams = self._oDisp.getParameters(); 552 if hasattr(self._oData, 'ksIdGenAttr'): 553 sIdGenParam = getattr(self._oData, 'ksParam_' + self._oData.ksIdGenAttr); 554 if sIdGenParam in dParams: 555 del dParams[sIdGenParam]; 556 if WuiDispatcherBase.ksParamEffectiveDate in dParams: 557 del dParams[WuiDispatcherBase.ksParamEffectiveDate]; 558 dParams[getattr(self._oData, 'ksParam_' + self._oData.ksIdAttr)] = getattr(self._oData, self._oData.ksIdAttr); 559 560 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Edit'); 561 aoActions.append(WuiTmLink('Edit', '', dParams)); 562 563 # Add clone operation if available. This uses the same data selection as for showing details. 564 if hasattr(self._oDisp, self._sActionBase + 'Clone'): 565 dParams = self._oDisp.getParameters(); 566 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Clone'); 567 aoActions.append(WuiTmLink('Clone', '', dParams)); 568 569 elif self._sMode == self.ksMode_Edit: 570 # Details views the details at a given time, so we need either idGen or an effecive date + regular id. 571 dParams = {}; 572 if hasattr(self._oData, 'ksIdGenAttr'): 573 sIdGenParam = getattr(self._oData, 'ksParam_' + self._oData.ksIdGenAttr); 574 dParams[sIdGenParam] = getattr(self._oData, self._oData.ksIdGenAttr); 575 elif hasattr(self._oData, 'tsEffective'): 576 dParams[WuiDispatcherBase.ksParamEffectiveDate] = self._oData.tsEffective; 577 dParams[getattr(self._oData, 'ksParam_' + self._oData.ksIdAttr)] = getattr(self._oData, self._oData.ksIdAttr); 578 dParams[WuiDispatcherBase.ksParamAction] = getattr(self._oDisp, self._sActionBase + 'Details'); 579 aoActions.append(WuiTmLink('Details', '', dParams)); 580 609 aoActions = self._generateTopRowFormActions(self._oData); 581 610 if len(aoActions) > 0: 582 611 sActionLinks = '<p>%s</p>' % (' '.join(unicode(oLink) for oLink in aoActions)); -
trunk/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py
r61225 r61250 124 124 # Non-input stuff. 125 125 # 126 def addNonText(self, sValue, sLabel, s PostHtml = ''):126 def addNonText(self, sValue, sLabel, sName = 'non-text', sPostHtml = ''): 127 127 """Adds a read-only text input.""" 128 self._addLabel( 'non-text', sLabel, 'string');128 self._addLabel(sName, sLabel, 'string'); 129 129 if sValue is None: sValue = ''; 130 return self._add(u' <p>%s </p>%s\n'130 return self._add(u' <p>%s%s</p>\n' 131 131 u' </div></div>\n' 132 132 u' </li>\n' 133 133 % (escapeElem(unicode(sValue)), sPostHtml )); 134 135 def addRawHtml(self, sRawHtml, sLabel, sName = 'raw-html'): 136 """Adds a read-only text input.""" 137 self._addLabel(sName, sLabel, 'string'); 138 self._add(sRawHtml); 139 return self._add(u' </div></div>\n' 140 u' </li>\n'); 134 141 135 142 -
trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py
r61239 r61250 36 36 from testmanager.webui.wuicontentbase import WuiTmLink; 37 37 from testmanager.core.report import ReportLazyModel, ReportGraphModel, ReportModelBase; 38 from testmanager.core.testresults import TestResultLogic, TestResultFileDataEx ;38 from testmanager.core.testresults import TestResultLogic, TestResultFileDataEx, TestResultData; 39 39 from testmanager.core.base import TMExceptionBase, TMTooManyRows; 40 40 from testmanager.core.testset import TestSetData, TestSetLogic; … … 68 68 ksActionResultsGroupedByTestBox = 'ResultsGroupedByTestBox' 69 69 ksActionResultsGroupedByTestCase = 'ResultsGroupedByTestCase' 70 ksActionTestResultDetails = 'TestResultDetails' 70 ksActionTestSetDetails = 'TestSetDetails'; 71 ksActionTestResultDetails = ksActionTestSetDetails; 72 ksActionTestSetDetailsFromResult = 'TestSetDetailsFromResult' 71 73 ksActionTestResultFailureDetails = 'TestResultFailureDetails' 72 74 ksActionTestResultFailureAdd = 'TestResultFailureAdd' … … 162 164 ## Test result period values. 163 165 kaoResultPeriods = [ 164 ( '1 hour', ' One hour',1 ),165 ( '2 hours', ' Two hours',2 ),166 ( '3 hours', ' Three hours',3 ),167 ( '6 hours', ' Six hours',6 ),166 ( '1 hour', '1 hour', 1 ), 167 ( '2 hours', '2 hours', 2 ), 168 ( '3 hours', '3 hours', 3 ), 169 ( '6 hours', '6 hours', 6 ), 168 170 ( '12 hours', '12 hours', 12 ), 169 171 170 ( '1 day', ' One day',24 ),171 ( '2 days', ' Two days',48 ),172 ( '3 days', ' Three days',72 ),173 174 ( '1 week', ' One week',168 ),175 ( '2 weeks', ' Two weeks',336 ),176 ( '3 weeks', ' Three weeks',504 ),177 178 ( '1 month', ' One month',31 * 24 ), # The approx hour count varies with the start date.179 ( '2 months', ' Two month',(31 + 31) * 24 ), # Using maximum values.180 ( '3 months', ' Three month',(31 + 30 + 31) * 24 ),181 182 ( '6 months', ' Six month',(31 + 31 + 30 + 31 + 30 + 31) * 24 ),183 184 ( '1 year', ' One year',365 * 24 ),172 ( '1 day', '1 day', 24 ), 173 ( '2 days', '2 days', 48 ), 174 ( '3 days', '3 days', 72 ), 175 176 ( '1 week', '1 week', 168 ), 177 ( '2 weeks', '2 weeks', 336 ), 178 ( '3 weeks', '3 weeks', 504 ), 179 180 ( '1 month', '1 month', 31 * 24 ), # The approx hour count varies with the start date. 181 ( '2 months', '2 months', (31 + 31) * 24 ), # Using maximum values. 182 ( '3 months', '3 months', (31 + 30 + 31) * 24 ), 183 184 ( '6 months', '6 months', (31 + 31 + 30 + 31 + 30 + 31) * 24 ), 185 186 ( '1 year', '1 year', 365 * 24 ), 185 187 ]; 186 188 ## The default test result period. … … 202 204 203 205 from testmanager.webui.wuitestresult import WuiGroupedResultList; 204 #d[self.ksActionResultsUnGrouped] = lambda: self._actionResultsListing(TestResultLogic, WuiGroupedResultList) 205 d[self.ksActionResultsUnGrouped] = lambda: self._actionGroupedResultsListing( 206 TestResultLogic.ksResultsGroupingTypeNone, 207 TestResultLogic, 206 #d[self.ksActionResultsUnGrouped] = lambda: self._actionResultsListing(TestResultLogic, WuiGroupedResultList) 207 d[self.ksActionResultsUnGrouped] = lambda: self._actionGroupedResultsListing( 208 TestResultLogic.ksResultsGroupingTypeNone, 209 TestResultLogic, 210 WuiGroupedResultList) 211 212 d[self.ksActionResultsGroupedByTestGroup] = lambda: self._actionGroupedResultsListing( 213 TestResultLogic.ksResultsGroupingTypeTestGroup, 214 TestResultLogic, 215 WuiGroupedResultList) 216 217 d[self.ksActionResultsGroupedByBuildRev] = lambda: self._actionGroupedResultsListing( 218 TestResultLogic.ksResultsGroupingTypeBuildRev, 219 TestResultLogic, 220 WuiGroupedResultList) 221 222 d[self.ksActionResultsGroupedByTestBox] = lambda: self._actionGroupedResultsListing( 223 TestResultLogic.ksResultsGroupingTypeTestBox, 224 TestResultLogic, 208 225 WuiGroupedResultList) 209 226 210 d[self.ksActionResultsGroupedByTestGroup] = lambda: self._actionGroupedResultsListing( 211 TestResultLogic.ksResultsGroupingTypeTestGroup, 212 TestResultLogic, 213 WuiGroupedResultList) 214 215 d[self.ksActionResultsGroupedByBuildRev] = lambda: self._actionGroupedResultsListing( 216 TestResultLogic.ksResultsGroupingTypeBuildRev, 217 TestResultLogic, 218 WuiGroupedResultList) 219 220 d[self.ksActionResultsGroupedByTestBox] = lambda: self._actionGroupedResultsListing( 221 TestResultLogic.ksResultsGroupingTypeTestBox, 222 TestResultLogic, 223 WuiGroupedResultList) 224 225 d[self.ksActionResultsGroupedByTestCase] = lambda: self._actionGroupedResultsListing( 226 TestResultLogic.ksResultsGroupingTypeTestCase, 227 TestResultLogic, 228 WuiGroupedResultList) 229 230 d[self.ksActionResultsGroupedBySchedGroup] = lambda: self._actionGroupedResultsListing( 231 TestResultLogic.ksResultsGroupingTypeSchedGroup, 232 TestResultLogic, 233 WuiGroupedResultList) 234 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; 242 243 d[self.ksActionViewLog] = self.actionViewLog; 244 d[self.ksActionGetFile] = self.actionGetFile; 227 d[self.ksActionResultsGroupedByTestCase] = lambda: self._actionGroupedResultsListing( 228 TestResultLogic.ksResultsGroupingTypeTestCase, 229 TestResultLogic, 230 WuiGroupedResultList) 231 232 d[self.ksActionResultsGroupedBySchedGroup] = lambda: self._actionGroupedResultsListing( 233 TestResultLogic.ksResultsGroupingTypeSchedGroup, 234 TestResultLogic, 235 WuiGroupedResultList) 236 237 d[self.ksActionTestSetDetails] = self._actionTestSetDetails; 238 d[self.ksActionTestSetDetailsFromResult] = self._actionTestSetDetailsFromResult; 239 240 d[self.ksActionTestResultFailureAdd] = self._actionTestResultFailureAdd; 241 d[self.ksActionTestResultFailureAddPost] = self._actionTestResultFailureAddPost; 242 d[self.ksActionTestResultFailureDetails] = self._actionTestResultFailureDetails; 243 d[self.ksActionTestResultFailureEdit] = self._actionTestResultFailureEdit; 244 d[self.ksActionTestResultFailureEditPost] = self._actionTestResultFailureEditPost; 245 246 d[self.ksActionViewLog] = self.actionViewLog; 247 d[self.ksActionGetFile] = self.actionGetFile; 245 248 from testmanager.webui.wuireport import WuiReportSummary, WuiReportSuccessRate, WuiReportFailureReasons; 246 d[self.ksActionReportSummary] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSummary); 247 d[self.ksActionReportRate] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSuccessRate); 248 d[self.ksActionReportFailureReasons] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportFailureReasons); 249 d[self.ksActionGraphWiz] = self._actionGraphWiz; 250 d[self.ksActionVcsHistoryTooltip] = self._actionVcsHistoryTooltip; 249 d[self.ksActionReportSummary] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSummary); 250 d[self.ksActionReportRate] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportSuccessRate); 251 d[self.ksActionReportFailureReasons] = lambda: self._actionGenericReport(ReportLazyModel, WuiReportFailureReasons); 252 d[self.ksActionGraphWiz] = self._actionGraphWiz; 253 d[self.ksActionVcsHistoryTooltip] = self._actionVcsHistoryTooltip; 254 255 # Legacy. 256 d['TestResultDetails'] = d[self.ksActionTestSetDetails]; 251 257 252 258 … … 389 395 ('+0000-00-00 00:00:00.00', 'Now', ' title="Present Day. Present Time."'), # lain :) 390 396 391 ('-0000-00-00 01:00:00.00', ' Onehour ago', ''),392 ('-0000-00-00 02:00:00.00', ' Twohours ago', ''),393 ('-0000-00-00 03:00:00.00', ' Threehours ago', ''),394 395 ('-0000-00-01 00:00:00.00', ' Oneday ago', ''),396 ('-0000-00-02 00:00:00.00', ' Twodays ago', ''),397 ('-0000-00-03 00:00:00.00', ' Threedays ago', ''),398 399 ('-0000-00-07 00:00:00.00', ' Oneweek ago', ''),400 ('-0000-00-14 00:00:00.00', ' Twoweeks ago', ''),401 ('-0000-00-21 00:00:00.00', ' Threeweeks ago', ''),402 403 ('-0000-01-00 00:00:00.00', ' Onemonth ago', ''),404 ('-0000-02-00 00:00:00.00', ' Twomonths ago', ''),405 ('-0000-03-00 00:00:00.00', ' Threemonths ago', ''),406 ('-0000-04-00 00:00:00.00', ' Fourmonths ago', ''),407 ('-0000-05-00 00:00:00.00', ' Fivemonths ago', ''),397 ('-0000-00-00 01:00:00.00', '1 hour ago', ''), 398 ('-0000-00-00 02:00:00.00', '2 hours ago', ''), 399 ('-0000-00-00 03:00:00.00', '3 hours ago', ''), 400 401 ('-0000-00-01 00:00:00.00', '1 day ago', ''), 402 ('-0000-00-02 00:00:00.00', '2 days ago', ''), 403 ('-0000-00-03 00:00:00.00', '3 days ago', ''), 404 405 ('-0000-00-07 00:00:00.00', '1 week ago', ''), 406 ('-0000-00-14 00:00:00.00', '2 weeks ago', ''), 407 ('-0000-00-21 00:00:00.00', '3 weeks ago', ''), 408 409 ('-0000-01-00 00:00:00.00', '1 month ago', ''), 410 ('-0000-02-00 00:00:00.00', '2 months ago', ''), 411 ('-0000-03-00 00:00:00.00', '3 months ago', ''), 412 ('-0000-04-00 00:00:00.00', '4 months ago', ''), 413 ('-0000-05-00 00:00:00.00', '5 months ago', ''), 408 414 ('-0000-06-00 00:00:00.00', 'Half a year ago', ''), 409 415 410 ('-0001-00-00 00:00:00.00', ' Oneyear ago', ''),416 ('-0001-00-00 00:00:00.00', '1 year ago', ''), 411 417 ] 412 418 fSelected = False; … … 842 848 return WuiDispatcherBase._generatePage(self) 843 849 844 def _actionTest ResultDetails(self):850 def _actionTestSetDetailsCommon(self, idTestSet): 845 851 """Show test case execution result details.""" 846 852 from testmanager.webui.wuitestresult import WuiTestResult; 847 853 848 854 self._sTemplate = 'template-details.html'; 849 idTestSet = self.getIntParam(TestSetData.ksParam_idTestSet);850 855 self._checkForUnknownParameters() 851 856 … … 878 883 return True 879 884 885 def _actionTestSetDetails(self): 886 """Show test case execution result details.""" 887 idTestSet = self.getIntParam(TestSetData.ksParam_idTestSet); 888 return self._actionTestSetDetailsCommon(idTestSet); 889 890 def _actionTestSetDetailsFromResult(self): 891 """Show test case execution result details.""" 892 idTestResult = self.getIntParam(TestSetData.ksParam_idTestResult); 893 oTestResultData = TestResultData().initFromDbWithId(self._oDb, idTestResult); 894 return self._actionTestSetDetailsCommon(oTestResultData.idTestSet); 895 896 880 897 def _actionTestResultFailureAdd(self): 881 898 """ Pro forma. """ … … 912 929 from testmanager.core.testresults import TestResultFailureLogic, TestResultFailureData; 913 930 from testmanager.webui.wuitestresultfailure import WuiTestResultFailure; 914 if self.ksParamRedirectTo not in self._dParams:915 raise WuiException('Missing parameter ' + self.ksParamRedirectTo);916 917 931 return self._actionGenericFormEditPost(TestResultFailureData, TestResultFailureLogic, 918 932 WuiTestResultFailure, self.ksActionResultsUnGrouped); -
trunk/src/VBox/ValidationKit/testmanager/webui/wuitestresult.py
r61238 r61250 32 32 33 33 # Validation Kit imports. 34 from testmanager.webui.wuicontentbase import WuiContentBase, WuiListContentBase, WuiHtmlBase, WuiTmLink, WuiLinkBase, \ 35 WuiSvnLink, WuiSvnLinkWithTooltip, WuiBuildLogLink, WuiRawHtml; 36 from testmanager.webui.wuimain import WuiMain; 37 from testmanager.webui.wuihlpform import WuiHlpForm; 38 from testmanager.core.failurereason import FailureReasonData, FailureReasonLogic; 39 from testmanager.core.report import ReportGraphModel; 40 from testmanager.core.testbox import TestBoxData; 41 from testmanager.core.testcase import TestCaseData; 42 from testmanager.core.testset import TestSetData; 43 from testmanager.core.testgroup import TestGroupData; 44 from testmanager.core.testresults import TestResultFailureData; 45 from testmanager.core.build import BuildData; 46 from testmanager.core import db; 47 from testmanager import config; 48 from common import webutils, utils; 49 50 51 class WuiFailureReasonDetailsLink(WuiTmLink): 52 """ Short link to a failure reason. """ 53 def __init__(self, idFailureReason, sName = WuiContentBase.ksShortDetailsLink, sTitle = None, fBracketed = None): 54 if fBracketed is None: 55 fBracketed = len(sName) > 2; 56 from testmanager.webui.wuiadmin import WuiAdmin; 57 WuiTmLink.__init__(self, sName = sName, 58 sUrlBase = WuiAdmin.ksScriptName, 59 dParams = { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonDetails, 60 FailureReasonData.ksParam_idFailureReason: idFailureReason, }, 61 fBracketed = fBracketed); 62 self.idFailureReason = idFailureReason; 63 64 class WuiFailureReasonAddLink(WuiTmLink): 65 """ Link for adding a failure reason. """ 66 def __init__(self, sName = WuiContentBase.ksShortAddLink, sTitle = None, fBracketed = None): 67 if fBracketed is None: 68 fBracketed = len(sName) > 2; 69 from testmanager.webui.wuiadmin import WuiAdmin; 70 WuiTmLink.__init__(self, sName = sName, 71 sUrlBase = WuiAdmin.ksScriptName, 72 dParams = { WuiAdmin.ksParamAction: WuiAdmin.ksActionFailureReasonAdd, }, 73 fBracketed = fBracketed); 34 from testmanager.webui.wuicontentbase import WuiContentBase, WuiListContentBase, WuiHtmlBase, WuiTmLink, WuiLinkBase, \ 35 WuiSvnLink, WuiSvnLinkWithTooltip, WuiBuildLogLink, WuiRawHtml; 36 from testmanager.webui.wuimain import WuiMain; 37 from testmanager.webui.wuihlpform import WuiHlpForm; 38 from testmanager.webui.wuiadminfailurereason import WuiFailureReasonAddLink, WuiFailureReasonDetailsLink; 39 from testmanager.webui.wuitestresultfailure import WuiTestResultFailureDetailsLink; 40 from testmanager.core.failurereason import FailureReasonData, FailureReasonLogic; 41 from testmanager.core.report import ReportGraphModel; 42 from testmanager.core.testbox import TestBoxData; 43 from testmanager.core.testcase import TestCaseData; 44 from testmanager.core.testset import TestSetData; 45 from testmanager.core.testgroup import TestGroupData; 46 from testmanager.core.testresults import TestResultFailureData; 47 from testmanager.core.build import BuildData; 48 from testmanager.core import db; 49 from testmanager import config; 50 from common import webutils, utils; 51 74 52 75 53 … … 401 379 oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, oData.idFailureReason, 'Reason', 402 380 aoFailureReasons, 403 sPostHtml = WuiFailureReasonDetailsLink(oData.idFailureReason).toHtml()); 381 sPostHtml = u' ' + WuiFailureReasonDetailsLink(oData.idFailureReason).toHtml() 382 + u' ' + WuiFailureReasonAddLink('New', fBracketed = False).toHtml()); 404 383 oForm.addMultilineText(TestResultFailureData.ksParam_sComment, oData.sComment, 'Comment') 405 384 406 oForm.addNonText('%s (%s), %s' % (oData.oAuthor.sUsername, oData.oAuthor.sUsername, self.formatTsShort(oData.tsEffective)), 'Sheriff'); 385 oForm.addNonText(u'%s (%s), %s' 386 % ( oData.oAuthor.sUsername, oData.oAuthor.sUsername, 387 self.formatTsShort(oData.tsEffective),), 388 'Sheriff', 389 sPostHtml = ' ' + WuiTestResultFailureDetailsLink(oData.idTestResult, "Show Details").toHtml() ) 390 407 391 oForm.addTextHidden(TestResultFailureData.ksParam_tsEffective, oData.tsEffective); 408 392 oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, oData.tsExpire); 409 393 oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, oData.uidAuthor); 394 oForm.addSubmit('Change Reason'); 395 410 396 else: 411 397 oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, -1, 'Reason', aoFailureReasons, … … 415 401 oForm.addTextHidden(TestResultFailureData.ksParam_tsExpire, ''); 416 402 oForm.addTextHidden(TestResultFailureData.ksParam_uidAuthor, ''); 417 418 oForm.addSubmit('Change Reason'); 403 oForm.addSubmit('Add Reason'); 404 419 405 sHtml += oForm.finalize(); 420 406 return sHtml; -
trunk/src/VBox/ValidationKit/testmanager/webui/wuitestresultfailure.py
r61217 r61250 30 30 31 31 # Validation Kit imports. 32 from testmanager.webui.wuicontentbase import WuiFormContentBase; 33 from testmanager.core.testresults import TestResultFailureData; 34 from testmanager.core.failurereason import FailureReasonLogic; 32 from testmanager.webui.wuicontentbase import WuiFormContentBase, WuiTmLink; 33 from testmanager.webui.wuimain import WuiMain; 34 from testmanager.webui.wuiadminfailurereason import WuiFailureReasonDetailsLink, WuiFailureReasonAddLink; 35 from testmanager.core.testresults import TestResultFailureData; 36 from testmanager.core.testset import TestSetData; 37 from testmanager.core.failurereason import FailureReasonLogic; 38 39 40 41 class WuiTestResultFailureDetailsLink(WuiTmLink): 42 """ Link for adding a failure reason. """ 43 def __init__(self, idTestResult, sName = u'\u2397', sTitle = None, fBracketed = None): 44 if fBracketed is None: 45 fBracketed = len(sName) > 2; 46 WuiTmLink.__init__(self, sName = sName, 47 sUrlBase = WuiMain.ksScriptName, 48 dParams = { WuiMain.ksParamAction: WuiMain.ksActionTestResultFailureDetails, 49 TestResultFailureData.ksParam_idTestResult: idTestResult, }, 50 fBracketed = fBracketed); 51 self.idTestResult = idTestResult; 52 35 53 36 54 … … 53 71 54 72 aoFailureReasons = FailureReasonLogic(self._oDisp.getDb()).fetchForCombo('Todo: Figure out why'); 73 sPostHtml = ''; 74 if oData.idFailureReason is not None and oData.idFailureReason >= 0: 75 sPostHtml += u' ' + WuiFailureReasonDetailsLink(oData.idFailureReason).toHtml(); 76 sPostHtml += u' ' + WuiFailureReasonAddLink('New', fBracketed = False).toHtml(); 55 77 oForm.addComboBox(TestResultFailureData.ksParam_idFailureReason, oData.idFailureReason, 56 'Reason', aoFailureReasons )78 'Reason', aoFailureReasons, sPostHtml = sPostHtml); 57 79 oForm.addMultilineText(TestResultFailureData.ksParam_sComment, oData.sComment, 'Comment'); 58 80 oForm.addIntRO( TestResultFailureData.ksParam_idTestResult, oData.idTestResult, 'Test Result ID'); … … 64 86 return True; 65 87 88 def _generateTopRowFormActions(self, oData): 89 """ 90 We add a way to get back to the test set to the actions. 91 """ 92 aoActions = super(WuiTestResultFailure, self)._generateTopRowFormActions(oData); 93 if oData and oData.idTestResult is not None and oData.idTestResult > 0: 94 aoActions.append(WuiTmLink('Associated Test Set', WuiMain.ksScriptName, 95 { WuiMain.ksParamAction: WuiMain.ksActionTestSetDetailsFromResult, 96 TestSetData.ksParam_idTestResult: oData.idTestResult } 97 )); 98 return aoActions; 99 100 101
Note:
See TracChangeset
for help on using the changeset viewer.