pyWinAuto: c:\.projects\py_pywinauto\pywinauto\tests\repeatedhotkey.py
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021"""Repeated Hotkeys Test
0022
0023**What is checked**
0024This test checks all the controls in a dialog to see if there are controls that
0025use the same hotkey character.
0026
0027**How is it checked**
0028A list of all the hotkeys (converted to uppercase) used in the dialog is
0029created. Then this list is examined to see if any hotkeys are used more than
0030once. If any are used more than once a list of all the controls that use this
0031hotkey are compiled to be used in the bug report.
0032
0033**When is a bug reported**
0034If more than one control has the same hotkey then a bug is reported.
0035
0036**Bug Extra Information**
0037The bug contains the following extra information
0038Name Description
0039RepeatedHotkey This is the hotkey that is repeated between the 2 controls
0040converted to uppercase, String
0041CharsUsedInDialog This is a list of all the hotkeys used in the dialog,
0042String
0043AllCharsInDialog This is a list of all the characters in the dialog for
0044controls that have a hotkeys, String
0045AvailableInControlS A list of the available characters for each control.
0046Any of the characters in this list could be used as the new hotkey without
0047conflicting with any existing hotkey.
0048
0049**Is Reference dialog needed**
0050The reference dialog does not need to be available. If it is available then
0051for each bug discovered it is checked to see if it is a problem in the
0052reference dialog.
0053NOTE: Checking the reference dialog is not so exact here! Only when the
0054equivalent controls in the reference dialog all have the hotkeys will it be
0055reported as being in the reference also. I.e. if there are 3 controls with the
0056same hotkey in the Localised software then those same controls in the
0057reference dialog must have the same hotkey for it to be reported as existing
0058in the reference also.
0059
0060**False positive bug reports**
0061There should be very few false positives from this test. Sometimes a control
0062only has one or 2 characters eg "X:" and it is impossible to avoid a hotkey
0063clash. Also for Asian languages hotkeys should be the same as the US software
0064so probably this test should be run on those languages.
0065
0066**Test Identifier**
0067The identifier for this test/bug is "RepeatedHotkey"
0068"""
0069
0070testname = "RepeatedHotkey"
0071__revision__ = "$Revision: 372 $"
0072
0073
0074
0075
0076import sets
0077
0078from pywinauto.win32defines import SS_NOPREFIX
0079
0080
0081
0082
0083def RepeatedHotkeyTest(windows):
0084 "Return the repeated hotkey errors"
0085
0086 hotkeyControls, allChars, hotkeys = _CollectDialogInfo(windows)
0087
0088
0089 dlgAvailable = allChars.difference(hotkeys)
0090
0091
0092 dlgAvailable.difference_update(sets.Set("-& _"))
0093
0094
0095 bugs = []
0096
0097 for char, controls in hotkeyControls.items():
0098
0099
0100 if len(controls) > 1:
0101
0102 ctrlsAvailableChars = ""
0103
0104
0105 for ctrl in controls:
0106 controlChars = ""
0107 controlChars = sets.Set(ctrl.WindowText().lower())
0108
0109 controlAvailableChars = controlChars.intersection(dlgAvailable)
0110 controlAvailableChars = "<%s>" % _SetAsString(controlAvailableChars)
0112
0113 ctrlsAvailableChars += controlAvailableChars
0114
0115 refCtrls = [ctrl.ref for ctrl in controls if ctrl.ref]
0116 refHotkeyControls, refAllChars, refHotkeys = _CollectDialogInfo(refCtrls)
0118
0119 isInRef = -1
0120 if len(refHotkeys) > 1:
0121 isInRef = 1
0122 else:
0123 isInRef = 0
0124
0125 bugs.append((
0126 controls,
0127 {
0128 "RepeatedHotkey" : char,
0129 "CharsUsedInDialog" : _SetAsString(hotkeys),
0130 "AllCharsInDialog" : _SetAsString(allChars),
0131 "AvailableInControls" : ctrlsAvailableChars,
0132 },
0133 testname,
0134 isInRef)
0135 )
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 return bugs
0150
0151
0152
0153
0154def _CollectDialogInfo(windows):
0155 "Collect information on the hotkeys in the dialog"
0156 hotkeyControls = {}
0157 allChars = ''
0158
0159 for win in windows:
0160
0161 if not ImplementsHotkey(win):
0162 continue
0163
0164
0165 pos, char = GetHotkey(win.WindowText())
0166
0167
0168
0169 if not char:
0170 continue
0171
0172
0173
0174 hotkeyControls.setdefault(char.lower(), []).append(win)
0175
0176
0177
0178
0179 allChars += win.WindowText().lower()
0180
0181
0182 allChars = sets.Set(allChars)
0183 hotkeys = sets.Set(hotkeyControls.keys())
0184
0185 return hotkeyControls, allChars, hotkeys
0186
0187
0188
0189
0190def GetHotkey(text):
0191 "Return the position and character of the hotkey"
0192
0193
0194
0195
0196 curEnd = len(text) + 1
0197 text = text.replace("&&", "__")
0198 while True:
0199 pos = text.rfind("&", 0, curEnd)
0200
0201
0202
0203
0204 if pos == -1 or pos == len(text):
0205 return (-1, '')
0206
0207
0208
0209 if text[pos - 1] == '&':
0210 curEnd = pos - 2
0211 continue
0212
0213
0214
0215 return (pos, text[pos+1])
0216
0217
0218
0219
0220def _SetAsString(settojoin):
0221 "Convert the set to a ordered string"
0222 return "".join(sorted(settojoin))
0223
0224
0225
0226def ImplementsHotkey(win):
0227 "checks whether a control interprets & character to be a hotkey"
0228
0229
0230 if win.Class() == "Button":
0231 return True
0232
0233
0234 elif win.Class() == "Static" and not win.HasStyle(SS_NOPREFIX):
0235 return True
0236
0237 if win.Class() == "MenuItem" and win.State() != "2048":
0238 return True
0239
0240
0241
0242 return False
0243
0244
0245RepeatedHotkeyTest.TestsMenus = True