Add more tests

This commit is contained in:
Digital Studium 2024-05-06 16:31:10 +03:00
parent 03bc2bc96d
commit 5165fa2aca
2 changed files with 67 additions and 21 deletions

16
kls
View File

@ -74,11 +74,11 @@ def draw_menu(menu: Menu):
draw_row(menu.win, f"/{menu.filter}" if menu.filter else "", curses.LINES - FOOTER_HEIGHT - 2, 2) # draw filter row draw_row(menu.win, f"/{menu.filter}" if menu.filter else "", curses.LINES - FOOTER_HEIGHT - 2, 2) # draw filter row
def refresh_third_menu(): def refresh_third_menu(namespace: str, api_resource: str):
menu = menus[2] menu = menus[2]
menu.rows = [] menu.rows = []
if api_resource() and namespace(): if api_resource and namespace:
menu.rows = kubectl(f"-n {namespace()} get {api_resource()} --no-headers --ignore-not-found") menu.rows = kubectl(f"-n {namespace} get {api_resource} --no-headers --ignore-not-found")
index_before_update = menu.filtered_rows.index index_before_update = menu.filtered_rows.index
menu.filtered_rows = CircularList([x for x in menu.rows if menu.filter in x]) # update filtered rows menu.filtered_rows = CircularList([x for x in menu.rows if menu.filter in x]) # update filtered rows
menu.filtered_rows.index = index_before_update menu.filtered_rows.index = index_before_update
@ -87,15 +87,15 @@ def refresh_third_menu():
draw_menu(menu) draw_menu(menu)
def handle_key_bindings(key: str, api_resource: str, resource: str): def handle_key_bindings(key: str, namespace: str, api_resource: str, resource: str):
if not menus[2].selected_row(): if not resource:
return return
if key in ("4", "5", "6"): if key in ("4", "5", "6"):
if api_resource not in ["pods", "all"] or (api_resource == "all" and not resource.startswith("pod/")): if api_resource not in ["pods", "all"] or (api_resource == "all" and not resource.startswith("pod/")):
return return
curses.def_prog_mode() # save the previous terminal state curses.def_prog_mode() # save the previous terminal state
curses.endwin() # without this, there are problems after exiting vim curses.endwin() # without this, there are problems after exiting vim
command = KEY_BINDINGS[key].format(namespace=namespace(), api_resource=api_resource, resource=resource) command = KEY_BINDINGS[key].format(namespace=namespace, api_resource=api_resource, resource=resource)
if api_resource == "all": if api_resource == "all":
command = command.replace(" all", "") command = command.replace(" all", "")
subprocess.call(command, shell=True) subprocess.call(command, shell=True)
@ -189,7 +189,7 @@ def catch_input(menu: Menu):
key = SCREEN.getkey() key = SCREEN.getkey()
break break
except curses.error: except curses.error:
refresh_third_menu() refresh_third_menu(namespace(), api_resource())
time.sleep(0.1) time.sleep(0.1)
if key in ["\t", "KEY_RIGHT", "KEY_BTAB", "KEY_LEFT"]: if key in ["\t", "KEY_RIGHT", "KEY_BTAB", "KEY_LEFT"]:
handle_horizontal_navigation(key, menu) handle_horizontal_navigation(key, menu)
@ -198,7 +198,7 @@ def catch_input(menu: Menu):
elif key == "KEY_MOUSE": elif key == "KEY_MOUSE":
handle_mouse(menu) handle_mouse(menu)
elif key in KEY_BINDINGS.keys(): elif key in KEY_BINDINGS.keys():
handle_key_bindings(key, api_resource(), resource()) handle_key_bindings(key, namespace(), api_resource(), resource())
elif key in ["\x1b", "KEY_BACKSPACE", "\x08"] or key.isalpha() or key == "-": # \x1b - escape, \x08 - backspace elif key in ["\x1b", "KEY_BACKSPACE", "\x08"] or key.isalpha() or key == "-": # \x1b - escape, \x08 - backspace
handle_filter_state(key, menu) handle_filter_state(key, menu)

View File

@ -6,10 +6,12 @@ os.system("ln -s kls kls.py")
import kls import kls
os.unlink('kls.py')
class TestCircularList(unittest.TestCase): class TestCircularList(unittest.TestCase):
def setUp(self): def setUp(self):
self.circular_list = kls.CircularList(['a', 'b', 'c']) self.circular_list = kls.CircularList(['kube-system', 'default', 'kube-public'])
def test_forward(self): def test_forward(self):
self.circular_list.shift(1) self.circular_list.shift(1)
@ -19,6 +21,9 @@ class TestCircularList(unittest.TestCase):
self.circular_list.shift(-1) self.circular_list.shift(-1)
self.assertEqual(self.circular_list.index, 2) # Since it's circular, it goes to the end self.assertEqual(self.circular_list.index, 2) # Since it's circular, it goes to the end
def tearDown(self):
kls.curses.endwin()
class TestScriptFunctions(unittest.TestCase): class TestScriptFunctions(unittest.TestCase):
@patch('kls.subprocess.check_output') @patch('kls.subprocess.check_output')
@ -27,26 +32,30 @@ class TestScriptFunctions(unittest.TestCase):
result = kls.kubectl('get pods') result = kls.kubectl('get pods')
self.assertEqual(result, ['pod1', 'pod2', 'pod3']) self.assertEqual(result, ['pod1', 'pod2', 'pod3'])
def tearDown(self):
kls.curses.endwin()
class TestMenu(unittest.TestCase): class TestMenu(unittest.TestCase):
def setUp(self): def setUp(self):
self.rows = ['a', 'b', 'c'] self.rows = ['kube-system', 'default', 'kube-public']
self.second_menu = kls.Menu("Test Menu 2", ["option1", "option2", "option3"], 0, 10, 2)
self.third_menu = kls.Menu("Test Menu 3", ["option1", "option2", "option3"], 0, 10, 2)
self.menu = kls.Menu('Test', self.rows, 0, 10, 2) self.menu = kls.Menu('Test', self.rows, 0, 10, 2)
self.second_menu = kls.Menu("Test Menu 2", ["pods", "services", "secrets"], 0, 10, 2)
self.third_menu = kls.Menu("Test Menu 3", ['pod1', 'pod2', 'pod3'], 0, 10, 2)
kls.menus = [self.menu, self.second_menu, self.third_menu] # Add the menu to the list of menus
os.system("ln -s kls kls.py") os.system("ln -s kls kls.py")
def test_menu(self): def test_menu(self):
self.assertEqual(self.menu.title, 'Test') self.assertEqual(self.menu.title, 'Test')
self.assertEqual(self.menu.filtered_rows.elements, self.rows) self.assertEqual(self.menu.filtered_rows.elements, self.rows)
self.assertEqual(self.menu.visible_rows(), ['a', 'b']) self.assertEqual(self.menu.visible_rows(), ['kube-system', 'default'])
self.assertEqual(self.menu.selected_row(), 'a') self.assertEqual(self.menu.selected_row(), 'kube-system')
def test_filter_rows_with_filter(self): def test_filter_rows_with_filter(self):
# Apply a filter and test # Apply a filter and test
self.menu.filter = 'a' self.menu.filter = 'kube-system'
self.menu.filtered_rows = kls.CircularList([x for x in self.menu.rows if self.menu.filter in x]) self.menu.filtered_rows = kls.CircularList([x for x in self.menu.rows if self.menu.filter in x])
self.assertEqual(self.menu.filtered_rows.elements, ['a']) self.assertEqual(self.menu.filtered_rows.elements, ['kube-system'])
def test_filter_rows_with_nonexistent_filter(self): def test_filter_rows_with_nonexistent_filter(self):
# Apply a filter that matches no rows # Apply a filter that matches no rows
@ -56,8 +65,6 @@ class TestMenu(unittest.TestCase):
def test_vertical_navigation(self): def test_vertical_navigation(self):
kls.selected_menu = self.menu kls.selected_menu = self.menu
# global menus
kls.menus = [self.menu, self.second_menu, self.third_menu] # Add the menu to the list of menus
# Test moving down one row # Test moving down one row
kls.handle_vertical_navigation("KEY_DOWN", self.menu) kls.handle_vertical_navigation("KEY_DOWN", self.menu)
self.assertEqual(self.menu.visible_row_index, 0) self.assertEqual(self.menu.visible_row_index, 0)
@ -82,10 +89,49 @@ class TestMenu(unittest.TestCase):
kls.handle_vertical_navigation("KEY_END", self.menu) kls.handle_vertical_navigation("KEY_END", self.menu)
self.assertEqual(self.menu.visible_row_index, -1) self.assertEqual(self.menu.visible_row_index, -1)
@patch('kls.subprocess.call')
@patch('kls.curses.reset_prog_mode')
@patch('kls.curses.def_prog_mode')
def test_handle_key_bindings(self, mock_def_prog_mode, mock_reset_prog_mode, mock_subprocess_call):
namespace = self.menu.selected_row()
api_resource = self.second_menu.selected_row()
resource = self.third_menu.selected_row()
key = "1" # Assuming you want to test the case where key is '1'
expected_command = kls.KEY_BINDINGS[key].format(namespace=namespace, api_resource=api_resource, resource=resource)
kls.handle_key_bindings(key, namespace, api_resource, resource)
mock_def_prog_mode.assert_called_once()
mock_reset_prog_mode.assert_called_once()
mock_subprocess_call.assert_called_once_with(expected_command, shell=True)
@patch('kls.curses.def_prog_mode')
def test_handle_key_bindings_empty_resource(self, mock_def_prog_mode):
namespace = self.menu.selected_row()
api_resource = self.second_menu.selected_row()
resource = None
key = "1" # Assuming you want to test the case where key is '1'
kls.handle_key_bindings(key, namespace, api_resource, resource)
mock_def_prog_mode.assert_not_called()
@patch('kls.curses.def_prog_mode')
def test_handle_key_bindings_services(self, mock_def_prog_mode):
namespace = self.menu.selected_row()
api_resource = "services"
resource = self.third_menu.selected_row()
key = "4" # 4 must not be called for services
kls.handle_key_bindings(key, namespace, api_resource, resource)
mock_def_prog_mode.assert_not_called()
def tearDown(self): def tearDown(self):
# Remove the symlink after each test os.unlink('kls.py') # Remove the symlink after each test
os.unlink('kls.py') kls.curses.endwin()
os.system("reset") print('\033[?1003l') # Disable mouse tracking with the XTERM API
if __name__ == '__main__': if __name__ == '__main__':