ui.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import PySimpleGUI as sg
  2. import glob
  3. import os
  4. import sys
  5. import platform
  6. import subprocess
  7. import configparser
  8. import baangt.base.GlobalConstants as GC
  9. from baangt.base.utils import utils
  10. from baangt.ui.ImportKatalonRecorder import ImportKatalonRecorder
  11. import logging
  12. import json
  13. from pathlib import Path
  14. logger = logging.getLogger("pyC")
  15. class UI:
  16. """
  17. Provides a simple UI for Testrun-Execution
  18. """
  19. def __init__(self):
  20. self.configFile = None
  21. self.tempConfigFile = None
  22. self.configFiles = []
  23. self.testRunFile = None
  24. self.testRunFiles = []
  25. self.configContents = {}
  26. self.window = None
  27. self.toggleAdditionalFieldsVisible = False
  28. self.iconFileWindow = b"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"
  29. self.directory = None
  30. self.mainWindowPosition = (None, None)
  31. self.readConfig()
  32. self.getConfigFilesInDirectory()
  33. self.startWindow()
  34. def getLayout(self):
  35. lMenu = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
  36. ['&Katalon Studio', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
  37. ['&Help', '&About...'], ]
  38. # lMenu doesnt' work. It shows up in the Mac-Menu, but none of the buttons work. Even the
  39. # Mac-Button stops working until the window is closed
  40. lColumnLeft = [[sg.Text("")],
  41. [sg.Text("Path", size=(10,1), font="Helvetica 10 bold"),
  42. sg.In(key="-directory-", size=(31,1), enable_events=True, default_text=self.directory, font="Helvetica 12"),
  43. sg.FolderBrowse(initial_folder=os.getcwd(), font="Helvetica 10", enable_events=True, size=(10,1))]]
  44. lColumnLeft.append([sg.Text("TestRun", size=(10, 1), font="Helvetica 10 bold"),
  45. sg.InputCombo(self.testRunFiles, key="testRunFile", default_value=self.testRunFile,
  46. size=(29, 1), font="Helvetica 12"),
  47. sg.Button("Execute", size=(10, 1), font="Helvetica 10", button_color=('white', 'darkgreen'))])
  48. lColumnLeft.append([sg.Text("Settings", size=(10, 1), font="Helvetica 10 bold"),
  49. sg.InputCombo(self.configFiles, key="configFile", default_value=self.configFile,
  50. enable_events=True, size=(29, 1), font="Helvetica 12"),
  51. sg.Button("Details", size=(10, 1), font="Helvetica 10", key="ToggleFields")])
  52. # Baangt Logo
  53. lPathLogo = Path(__file__).parent.parent.parent.joinpath("ressources").joinpath("baangtLogo.png")
  54. # when in pip-Package, this doesn't work.
  55. if not lPathLogo.exists():
  56. lPathLogo = Path(__file__).parent.parent.joinpath("ressources").joinpath("baangtLogo.png")
  57. lColumnRight = [[sg.Image(filename=lPathLogo)]]
  58. lLayout = [[sg.Menu(lMenu)],
  59. [sg.Col(lColumnLeft, pad=(0,0)),
  60. sg.Col(lColumnRight, pad=(0,0), justification="right")]]
  61. # Show the button to provide more details
  62. ttip_Recorder = 'Will start the Katalon Recorder Importer'
  63. if self.configContents:
  64. lLayout.append([sg.Text(f"SETTINGS IN {self.configFile}", font="Helvetica 8 bold",
  65. visible=self.toggleAdditionalFieldsVisible)])
  66. for key, value in self.configContents.items():
  67. lLayout.append([sg.In(key, key="-attrib-" + key, size=(28,1), visible=self.toggleAdditionalFieldsVisible),
  68. sg.In(key="-val-"+key, size=(34,1), default_text=value, visible=self.toggleAdditionalFieldsVisible)])
  69. for i in range(0,4):
  70. lLayout.append([sg.In(key=f"-newField-{i}", size=(28,1), visible=self.toggleAdditionalFieldsVisible),
  71. sg.In(key=f"-newValue-{i}", size=(34,1), visible=self.toggleAdditionalFieldsVisible)])
  72. lLayout.append([sg.Button('Save', size=(13,1)),
  73. sg.Button("SaveAs", size=(13,1)),
  74. sg.Button("Import Recorder", size=(13,1), tooltip=ttip_Recorder),
  75. sg.Button("Import Katalon", size=(13,1), disabled=True),])
  76. lLayout.append([sg.T()])
  77. return lLayout
  78. def startWindow(self):
  79. sg.theme("LightBrown1")
  80. self.window = sg.Window("baangt Interactive Starter", layout=self.getLayout(), location=self.mainWindowPosition,
  81. icon=self.iconFileWindow) # size=(750,400)
  82. lWindow = self.window
  83. lWindow.finalize()
  84. # lWindow.set_icon(pngbase64=self.iconFileWindow)
  85. # sg.theme_previewer()
  86. while True:
  87. lEvent, lValues = lWindow.read(timeout=200)
  88. if lEvent == "Exit":
  89. break
  90. if not lEvent: # Window was closed by "X"-Button
  91. break
  92. self.mainWindowPosition = lWindow.CurrentLocation()
  93. if lValues.get('-directory-') != self.directory:
  94. self.directory = lValues.get("-directory-")
  95. self.getConfigFilesInDirectory()
  96. lWindow['configFile'].update(values=self.configFiles, value="")
  97. lWindow['testRunFile'].update(values=self.testRunFiles, value="")
  98. lValues['configFile'] = ""
  99. if lValues["testRunFile"]:
  100. self.testRunFile = lValues["testRunFile"]
  101. if lValues["configFile"]:
  102. if lValues["configFile"] != self.configFile:
  103. self.configFile = lValues['configFile']
  104. self.readContentsOfGlobals()
  105. lWindow = self.reopenWindow(lWindow)
  106. if lEvent == 'Save':
  107. lWindow = self.saveConfigFileProcedure(lWindow, lValues)
  108. if lEvent == 'SaveAs':
  109. self.configFile = sg.popup_get_text("New Name of Configfile:")
  110. if len(self.configFile) > 0:
  111. lWindow = self.saveConfigFileProcedure(lWindow, lValues)
  112. if lEvent == "Execute":
  113. self.modifyValuesOfConfigFileInMemory(lValues=lValues)
  114. self.runTestRun()
  115. if lEvent == "Import KatalonRecorder":
  116. ImportKatalonRecorder(self.directory)
  117. self.getConfigFilesInDirectory() # Refresh display
  118. if lEvent == 'ToggleFields':
  119. lWindow = self.toggleAdditionalFieldsExecute(lWindow=lWindow)
  120. self.saveInteractiveGuiConfig()
  121. lWindow.close()
  122. def saveConfigFileProcedure(self, lWindow, lValues):
  123. # receive updated fields and values to store in JSON-File
  124. self.modifyValuesOfConfigFileInMemory(lValues)
  125. self.saveContentsOfConfigFile()
  126. lWindow = self.reopenWindow(lWindow)
  127. return lWindow
  128. def reopenWindow(self, lWindow):
  129. lSize = lWindow.Size
  130. lPosition = lWindow.CurrentLocation()
  131. lWindow.close()
  132. self.window = sg.Window("baangt Interactive Starter", layout=self.getLayout(),
  133. location=lPosition, icon=self.iconFileWindow)
  134. lWindow = self.window
  135. lWindow.finalize()
  136. return lWindow
  137. def toggleAdditionalFieldsExecute(self, lWindow):
  138. if self.toggleAdditionalFieldsVisible:
  139. self.toggleAdditionalFieldsVisible = False
  140. else:
  141. self.toggleAdditionalFieldsVisible = True
  142. lWindow = self.reopenWindow(lWindow=lWindow)
  143. return lWindow
  144. def runTestRun(self):
  145. if not self.configFile:
  146. sg.popup_cancel("No Config File selected - can't run")
  147. return
  148. if not self.testRunFile:
  149. sg.popup_cancel("No Testrun File selected - can't run")
  150. return
  151. runCmd = self._getRunCommand()
  152. logger.info(f"Running command: {runCmd}")
  153. p = subprocess.run(runCmd, shell=True)
  154. sg.popup_ok("Testrun finished")
  155. # Remove temporary Configfile, that was created only for this run:
  156. try:
  157. os.remove(Path(self.directory).joinpath(self.tempConfigFile))
  158. except Exception as e:
  159. logger.warning(f"Tried to remove temporary file but seems to be not there: "
  160. f"{self.directory}/{self.tempConfigFile}")
  161. def _getRunCommand(self):
  162. """
  163. If bundled (e.g. in pyinstaller), then the executable is already sys.executable,
  164. otherwise we need to concatenate executable and Script-Name before we can start
  165. a subprocess.
  166. @return: Full path and filename to call Subprocess
  167. """
  168. lStart = sys.executable
  169. if "python" in sys.executable.lower():
  170. if len(Path(sys.argv[0]).parents) > 1:
  171. # This is a system where the path the the script is given in sys.argv[0]
  172. lStart = lStart + f" {sys.argv[0]}"
  173. else:
  174. # this is a system where we need to join os.getcwd() and sys.argv[0] because the path is not given in sys.argv[0]
  175. lStart = lStart + f" {Path(os.getcwd()).joinpath(sys.argv[0])}"
  176. self.__makeTempConfigFile()
  177. return f"{lStart} " \
  178. f"--run='{Path(self.directory).joinpath(self.testRunFile)}' " \
  179. f"--globals='{Path(self.directory).joinpath(self.tempConfigFile)}'"
  180. def __makeTempConfigFile(self):
  181. """
  182. Add parameters to the Config-File for this Testrun and save the file under a temporary name
  183. """
  184. self.configContents[GC.PATH_ROOT] = self.directory
  185. self.configContents[GC.PATH_SCREENSHOTS] = str(Path(self.directory).joinpath("Screenshots"))
  186. self.configContents[GC.PATH_EXPORT] = str(Path(self.directory).joinpath("1testoutput"))
  187. self.configContents[GC.PATH_IMPORT] = str(Path(self.directory).joinpath("0testdateninput"))
  188. self.tempConfigFile = UI.__makeRandomFileName()
  189. self.saveContentsOfConfigFile(self.tempConfigFile)
  190. @staticmethod
  191. def __makeRandomFileName():
  192. return "globals_" + utils.datetime_return() + ".json"
  193. def _getPythonExecutable(self):
  194. if hasattr(sys, '_MEIPASS'):
  195. # We're in an executable created by pyinstaller
  196. return sys.executable
  197. if platform.system().lower() == 'linux' or platform.system().lower() == 'darwin':
  198. lPython = 'python3'
  199. elif platform.system().lower() == 'windows':
  200. lPython = 'python'
  201. else:
  202. sys.exit(f"Unknown platform to run on: {platform.system().lower()}")
  203. return lPython
  204. def getConfigFilesInDirectory(self):
  205. """
  206. Reads JSON-Files from directory given in self.directory and builds 2 lists (Testrunfiles and ConfiFiles)
  207. """
  208. self.configFiles = []
  209. self.testRunFiles = []
  210. lcwd = os.getcwd()
  211. os.chdir(self.directory)
  212. fileList = glob.glob("*.json")
  213. fileList.extend(glob.glob("*.xlsx"))
  214. if not platform.system().lower() == 'windows':
  215. # On MAC and LINUX there may be also upper/lower-Case versions
  216. fileList.extend(glob.glob("*.JSON"))
  217. fileList.extend(glob.glob("*.XLSX"))
  218. for file in fileList:
  219. if file[0:4].lower() == 'glob': # Global Settings for Testrun must start with global_*
  220. self.configFiles.append(file)
  221. else:
  222. self.testRunFiles.append(file)
  223. pass
  224. self.configFiles = sorted(self.configFiles)
  225. self.testRunFiles = sorted(self.testRunFiles)
  226. os.chdir(lcwd)
  227. def readContentsOfGlobals(self):
  228. self.configContents = utils.openJson(Path(self.directory).joinpath(self.configFile))
  229. # Prepare some default values, if not filled:
  230. if not self.configContents.get("TC." + GC.DATABASE_LINES):
  231. self.configContents["TC." + GC.DATABASE_LINES] = ""
  232. if not self.configContents.get("TC." + GC.EXECUTION_DONTCLOSEBROWSER):
  233. self.configContents["TC." + GC.EXECUTION_DONTCLOSEBROWSER] = ""
  234. if not self.configContents.get("TC." + GC.EXECUTION_SLOW):
  235. self.configContents["TC." + GC.EXECUTION_SLOW] = ""
  236. def saveContentsOfConfigFile(self, lFileName = None):
  237. if not lFileName:
  238. lFileName = self.configFile
  239. with open(str(Path(self.directory).joinpath(lFileName)), 'w') as outfile:
  240. json.dump(self.configContents, outfile, indent=4)
  241. def modifyValuesOfConfigFileInMemory(self, lValues):
  242. for key, value in lValues.items():
  243. if not isinstance(key, str):
  244. continue
  245. if '-attrib-' in key:
  246. # Existing field - update value from value
  247. lSearchKey = key.replace("-attrib-","")
  248. if lSearchKey != value:
  249. # an existing variable was changed to a new name. Delete the old one:
  250. self.configContents.pop(lSearchKey)
  251. lSearchKey = value
  252. lSearchVal = lValues['-val-'+key.replace("-attrib-", "")]
  253. else:
  254. lSearchVal = lValues['-val-'+lSearchKey]
  255. if len(lSearchKey) > 0:
  256. self.configContents[lSearchKey] = lSearchVal
  257. elif '-newField-' in key:
  258. # New field needs to be added to memory:
  259. lSearchKey = value # the new fieldname
  260. if len(lSearchKey) > 0:
  261. lSearchVal = lValues['-newValue-'+key[-1]]
  262. self.configContents[lSearchKey] = lSearchVal
  263. elif '-val-' in key or '-newValue-':
  264. pass # Values have been used already above
  265. else:
  266. logger.critical(f"Program error. Received something with key {key}, value {value} and no "
  267. f"idea what to do with it")
  268. def saveInteractiveGuiConfig(self):
  269. config = configparser.ConfigParser()
  270. config["DEFAULT"] = {"path": self.directory,
  271. "testrun": UI.__nonEmptyString(self.testRunFile),
  272. "globals": UI.__nonEmptyString(self.configFile),
  273. "position": self.mainWindowPosition}
  274. with open("baangt.ini", "w") as configFile:
  275. config.write(configFile)
  276. @staticmethod
  277. def __nonEmptyString(stringIn):
  278. if stringIn:
  279. return stringIn
  280. else:
  281. return ""
  282. def readConfig(self):
  283. config = configparser.ConfigParser()
  284. try:
  285. config.read("baangt.ini")
  286. self.directory = config["DEFAULT"]['path']
  287. self.testRunFile = config["DEFAULT"]['testrun']
  288. self.configFile = config["DEFAULT"]['globals']
  289. self.mainWindowPosition = UI.__convert_configPosition2Tuple(config["DEFAULT"]['position'])
  290. # Value in there is now a string of "(x-coordinates, y-coordinates)". We need a tuple (int:x, int:y)
  291. self.readContentsOfGlobals()
  292. except Exception as e:
  293. self.directory = os.getcwd()
  294. pass
  295. @staticmethod
  296. def __convert_configPosition2Tuple(inString):
  297. x = int(inString.split(",")[0].lstrip("("))
  298. y = int(inString.split(",")[1].rstrip(")"))
  299. return (x,y)