Skip to content

Commit

Permalink
Merge pull request #10 from QAInsights/feat/recent-test-plans-menu
Browse files Browse the repository at this point in the history
Feature: Recent Test Plans Menu
  • Loading branch information
QAInsights authored Nov 18, 2023
2 parents 5e73de2 + bb2c979 commit 5b658af
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
7 changes: 4 additions & 3 deletions hamster/__main__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import config, menu, utils


def main():
"""
Entry point of the Hamster - menu bar application.
"""
utils.prechecks(config.jmeter_plist, config.jmeter_home, config.jmeter_path)
menu_items = utils.get_recent_jmeter_test_plans()
menu.DynamicMenuApp("JMeter", menu_items).run()
menu_builder = menu.DynamicMenuApp("JMeter")
menu_builder.run()


if __name__ == "__main__":
main()
8 changes: 6 additions & 2 deletions hamster/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
pattern = re.compile("recent_file_.*")

jmeter_plist = f"/Users/{username}/Library/Preferences/org.apache.jmeter.plist"
jmeter_home = config_parser.get('JMETER', 'HOME')
jmeter_path = jmeter_home + '/bin/jmeter'


def jmeter_path():
jmeter_home = config_parser.get('JMETER', 'HOME')
jmeter_bin = jmeter_home + '/bin/jmeter'
return jmeter_home, jmeter_bin
63 changes: 46 additions & 17 deletions hamster/menu.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import rumps
import subprocess
from utils import restart, update_properties, show_splash_screen
from config import jmeter_path, icon_path, properties_file_path, config_parser
from utils import update_properties, show_splash_screen, prechecks, get_recent_jmeter_test_plans, sleep
from config import jmeter_path, icon_path, properties_file_path, config_parser, jmeter_plist


class DynamicMenuApp(rumps.App):
Expand All @@ -10,7 +10,6 @@ class DynamicMenuApp(rumps.App):
Attributes:
title (str): The title of the application.
menu_items (list): A list of menu items.
Methods:
__init__(self, title, menu_items): Initializes the DynamicMenuApp object.
Expand All @@ -22,17 +21,42 @@ class DynamicMenuApp(rumps.App):
just_jmeter(self, _): Launches JMeter without any test plan.
about(self, _): Displays information about the application.
"""
def __init__(self, title, menu_items):
def __init__(self, title):
super(DynamicMenuApp, self).__init__(title, icon=icon_path, quit_button='Quit')
self.menu = ['Just JMeter', None] + [rumps.MenuItem(item, callback=self.menu_callback) for item in menu_items] \
+ [None, 'View Config', 'Edit JMETER_HOME'] + [None, 'Restart', None, 'Help', 'About']

@rumps.clicked("Restart")
def restart(self, _):
self.menu = ['Launch JMeter', 'Recent Test Plans', None, 'View Config', 'Edit JMETER_HOME', None,
'Refresh', 'Help', 'About']
self.jmeter_home, self.jmeter_bin = jmeter_path()
prechecks(jmeter_plist, self.jmeter_home, self.jmeter_bin)
self.refresh_test_plans(delay=1)

def refresh_test_plans(self, delay=5):
"""
Restarts the application.
Refreshes Recent Test Plans Menu Items
Args:
delay: in seconds, defaults to 5
Returns: None
"""
restart(1)
sleep(delay)
recent_test_plans_menu = self.menu["Recent Test Plans"]
if recent_test_plans_menu:
recent_test_plans_menu.clear()

recent_test_plans = get_recent_jmeter_test_plans()
if not len(recent_test_plans) > 0:
recent_test_plans_menu.add(rumps.MenuItem("No recent JMeter test plans files found."))
return

for test_plan in recent_test_plans:
recent_test_plans_menu.add(rumps.MenuItem(test_plan, callback=self.menu_callback))

@rumps.clicked("Refresh")
def refresh(self, _):
"""
Refreshes Test Plans
"""
self.refresh_test_plans(1)

@rumps.clicked("Help")
def help(self, _):
Expand All @@ -58,15 +82,19 @@ def edit_home_path(self, _):
Allows the user to edit the JMETER_HOME path.
"""
try:
window_builder = rumps.Window(message='Enter absolute JMETER_HOME path', cancel="Cancel", dimensions=(300, 100))
window_builder = rumps.Window(message='Enter absolute JMETER_HOME path', cancel="Cancel",
dimensions=(300, 100))
window_builder.default_text = config_parser.get('JMETER', 'HOME')
window_builder.icon = icon_path
window_builder.title = "Configure JMETER_HOME"

response = window_builder.run()

if response.clicked:
update_properties({'HOME': str(response.text)})
updated_jmeter_home = response.text.strip()
update_properties({'HOME': str(updated_jmeter_home)})
config_parser.read(properties_file_path)
self.jmeter_home, self.jmeter_bin = jmeter_path()
self.refresh_test_plans(1)
except Exception as e:
rumps.alert("Error", e)

Expand All @@ -75,17 +103,18 @@ def menu_callback(self, sender):
Callback function for menu items.
"""
try:
subprocess.Popen([jmeter_path, '-t', sender.title], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.Popen([self.jmeter_bin, '-t', sender.title], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
self.refresh_test_plans()
except Exception as e:
rumps.alert("Error", e)

@rumps.clicked("Just JMeter")
@rumps.clicked("Launch JMeter")
def just_jmeter(self, _):
"""
Launches JMeter without any test plan.
"""
try:
subprocess.Popen([jmeter_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.Popen([self.jmeter_bin], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except Exception as e:
rumps.alert("Error", e)

Expand Down
18 changes: 3 additions & 15 deletions hamster/utils.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import os
import plistlib
import psutil
import time
import sys
import rumps

from pathlib import Path
from config import properties_file_path, config_parser, jmeter_plist, pattern, icon_path


def restart(delay):
if delay:
time.sleep(delay)
else:
time.sleep(1)
python = sys.executable
psutil.Popen([python] + sys.argv)
psutil.Process(os.getpid()).terminate()
def sleep(delay=1):
time.sleep(delay)


def refresh_plist(plist_path):
Expand Down Expand Up @@ -49,13 +40,10 @@ def get_recent_jmeter_test_plans():
recent_files = {k: v for k, v in pl['/org/apache/jmeter/']["gui/"]["action/"].items() if pattern.match(k)}

# escape file names with spaces
recent_files = {k: v.replace(' ', '\\ ') for k, v in recent_files.items()}
recent_files = {k: v for k, v in recent_files.items()}
recent_files = dict(sorted(recent_files.items()))
recent_files = list(recent_files.values())

# check if recent_files is empty
if not recent_files:
recent_files.append("No recent JMeter test plans files found.")
except Exception as e:
rumps.alert("Error", e)

Expand Down

0 comments on commit 5b658af

Please sign in to comment.