diff --git a/soitool/modules/module_authentification_board.py b/soitool/modules/module_authentification_board.py index a25512c40e2b7d09bc5dd51ceee2cf793fb89701..11e6091a6792cb1507175274743d2afd80fbc4ba 100644 --- a/soitool/modules/module_authentification_board.py +++ b/soitool/modules/module_authentification_board.py @@ -14,7 +14,7 @@ from soitool.modules.module_base import ( START_NO_OF_AUTHENTICATION_CODES = 10 CODE_LENGTH = 26 CODE_CHARACTERS = string.ascii_uppercase # Codes consist of these characters -ROW_IDENTIFIERS = string.ascii_uppercase # Characters for second column, +ROW_IDENTIFIERS = string.ascii_uppercase # Characters for first column, # it's length determines maximum number of codes (rows). SEPARATE_INTERVAL = 5 # Adds space between sets of characters, 0 => no spaces # If code is 123456 and interval is 2, code will be 12 34 56 @@ -152,7 +152,9 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta): start = SEPARATE_INTERVAL # Separate code with spaces - for i in range(start, len(code), SEPARATE_INTERVAL): + for i in range( + start, len(code) - SEPARATE_INTERVAL, SEPARATE_INTERVAL + ): code[i] += " " return "".join(code) @@ -245,8 +247,8 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta): Returns ------- - List (2D) - list[0][0] contains headline, + List + List[0] contains headline, list[x][y] represents value of row x, column y. """ content = [] @@ -303,10 +305,10 @@ def generate_authentification_codes(amount=START_NO_OF_AUTHENTICATION_CODES): start = SEPARATE_INTERVAL - 1 else: start = SEPARATE_INTERVAL - for j in range( + for i in range( start, len(sequence) - SEPARATE_INTERVAL, SEPARATE_INTERVAL ): - sequence[j] += " " + sequence[i] += " " codes.append("".join(sequence)) return codes diff --git a/test/test_module_authentification_board.py b/test/test_module_authentification_board.py new file mode 100644 index 0000000000000000000000000000000000000000..19a1773d79413499724c606db0d21128487f676c --- /dev/null +++ b/test/test_module_authentification_board.py @@ -0,0 +1,173 @@ +"""Test AuthentificationBoardModule.""" +import unittest +from PySide2 import QtGui +from PySide2.QtWidgets import QApplication +from PySide2.QtCore import Qt +from PySide2.QtTest import QTest +from soitool.modules.module_authentification_board import ( + AuthentificationBoardModule, + START_NO_OF_AUTHENTICATION_CODES, + HEADLINE_TEXT, + ROW_IDENTIFIERS, + CODE_LENGTH, + CODE_CHARACTERS, +) +from soitool.soi import SOI + +if isinstance(QtGui.qApp, type(None)): + app = QApplication([]) +else: + app = QtGui.qApp + + +class TestDefaultAuthentificationBoardModule(unittest.TestCase): + """TestCase for AuthentificationBoardModule.""" + + def setUp(self): + """Create new AuthentificationBoardModule.""" + self.module = AuthentificationBoardModule() + + def test_default_module(self): + """Test that module is initialized properly.""" + # Assert correct headline + self.assertEqual(self.module.item(0, 0).text(), HEADLINE_TEXT) + + # Assert correct number of rows including header + self.assertEqual( + self.module.rowCount(), START_NO_OF_AUTHENTICATION_CODES + 1 + ) + # Assert correct number of columns + self.assertEqual(self.module.columnCount(), 3) + + # Assert cell content in first column is correct + self.assertEqual(self.module.item(1, 0).text(), ROW_IDENTIFIERS[0]) + self.assertEqual(self.module.item(2, 0).text(), ROW_IDENTIFIERS[1]) + + # Assert cell content in second column is correct + self.assertEqual(self.module.item(1, 1).text(), "0") + self.assertEqual(self.module.item(2, 1).text(), "1") + + # Assert cell content in third column is correct + code = self.module.item(1, 2).text() + self.assertTrue(len(code) >= CODE_LENGTH) + # Assert all code characters are taken from list CODE_CHARACTERS + for _, character in enumerate(code): + if character != " ": + self.assertTrue(character in CODE_CHARACTERS) + # Assert all codes are unique + code_list = self.module.get_codes() + code_set = set(code_list) + self.assertEqual(len(code_list), len(code_set)) + + def test_generate_unique_authentification_code(self): + """Test function generate_unique_authentification_module.""" + code_list = self.module.get_codes() + generated_code = self.module.generate_unique_authentification_code() + + # Assert code length is equal to an existing code + self.assertEqual(len(generated_code), len(code_list[0])) + # Assert generated code is not equal to any existing codes + self.assertFalse(generated_code in code_list) + + def test_get_codes(self): + """Test function get_codes.""" + # Get codes + code_list = self.module.get_codes() + + # Assert codes are correct + for i, code in enumerate(code_list): + self.assertEqual(code, self.module.item(i + 1, 2).text()) + + def test_gui_add_row(self): + """Test adding rows with shortcuts.""" + # Widget must be shown for shortcuts to work + self.module.show() + QTest.qWaitForWindowExposed(self.module) + + old_row_count = self.module.rowCount() + + # Use shortcut 'Ctrl + +' + QTest.keyClicks(self.module, "+", Qt.ControlModifier) + + # Assert a new row is added + new_row_count = self.module.rowCount() + self.assertEqual(old_row_count + 1, new_row_count) + + # Assert new row has correct content + row_index = new_row_count - 1 + self.assertEqual( + self.module.item(row_index, 0).text(), + ROW_IDENTIFIERS[row_index - 1], + ) + self.assertEqual( + self.module.item(row_index, 1).text(), str(row_index - 1) + ) + new_code = self.module.item(row_index, 2).text() + existing_code = self.module.item(1, 2).text() + self.assertEqual(len(new_code), len(existing_code)) + + def test_gui_remove_row(self): + """Test removing rows with shortcuts.""" + # Widget must be shown for shortcuts to work + self.module.show() + QTest.qWaitForWindowExposed(self.module) + + old_row_count = self.module.rowCount() + + # First row is selected on startup, it contains headline + # and user should not be able to delete it with shortcut + QTest.keyClicks(self.module, "_", Qt.ControlModifier) + # Assert row was not removed + new_row_count = self.module.rowCount() + self.assertEqual(old_row_count, new_row_count) + + # Move to first row, then use shortcut to delete it + QTest.keyClick(self.module, Qt.Key_Down) + QTest.keyClicks(self.module, "_", Qt.ControlModifier) + # Assert row was removed and replaced by the row below + value_to_delete = self.module.item(1, 1).text() + new_row_count = self.module.rowCount() + self.assertEqual(old_row_count - 1, new_row_count) + self.assertEqual(self.module.item(1, 1).text(), value_to_delete) + + # Remove rows until only headline-row and a single code-row exist + for _ in range(1, self.module.rowCount() - 1): + QTest.keyClick(self.module, Qt.Key_Down) + QTest.keyClicks(self.module, "_", Qt.ControlModifier) + self.assertTrue(self.module.rowCount() == 2) + # Try to remove final code-row, should not work + QTest.keyClick(self.module, Qt.Key_Down) + QTest.keyClicks(self.module, "_", Qt.ControlModifier) + # Assert row was not removed + self.assertTrue(self.module.rowCount() == 2) + + def test_add_to_soi_smoke_test(self): + """Test that module can be added to SOI.""" + soi = SOI() + module_name = "Test name" + soi.add_module(module_name, self.module) + self.assertTrue(soi.module_name_taken(module_name)) + + +class TestAuthentificationBoardModuleFromData(unittest.TestCase): + """TestCase for initializing AuthentificationBoardModule from data.""" + + def test_create_from_data(self): + """Test creating AuthentificationBoardModule from data.""" + test_data = [ + "Headline text", + ["A", "0", "TEST CODE ONE"], + ["B", "1", "TEST CODE TWO"], + ] + test_size = {"width": 100, "height": 100} + + module = AuthentificationBoardModule(size=test_size, data=test_data) + + # Assert module contains expected data + self.assertEqual(module.item(0, 0).text(), "Headline text") + self.assertEqual(module.item(1, 0).text(), "A") + self.assertEqual(module.item(1, 1).text(), "0") + self.assertEqual(module.item(1, 2).text(), "TEST CODE ONE") + self.assertEqual(module.item(2, 0).text(), "B") + self.assertEqual(module.item(2, 1).text(), "1") + self.assertEqual(module.item(2, 2).text(), "TEST CODE TWO")