Skip to content
Snippets Groups Projects
test_module_authentication_and_subtractor.py 9.71 KiB
Newer Older
"""Test AuthenticationBoardModule."""
import unittest
import string
from PySide2 import QtGui
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import Qt, QTimer
from PySide2.QtTest import QTest
from soitool.modules.module_authentication_board import (
    AuthenticationBoardModule,
    START_NO_OF_CODES as START_NO_OF_CODES_AUTHENTICATION,
    HEADLINE_TEXT as HEADLINE_TEXT_AUTHENTICATION,
    ROW_IDENTIFIERS as ROW_IDENTIFIERS_AUTHENTICATION,
    CODE_LENGTH as CODE_LENGTH_AUTHENTICATION,
)
from soitool.modules.module_subtractorcodes import (
    SubtractorcodesModule,
    START_NO_OF_CODES as START_NO_OF_CODES_SUBTRACTOR,
    HEADLINE_TEXT as HEADLINE_TEXT_SUBTRACTOR,
    ROW_IDENTIFIERS as ROW_IDENTIFIERS_SUBTRACTOR,
    CODE_LENGTH as CODE_LENGTH_SUBTRACTOR,
)
from soitool.soi import SOI

if isinstance(QtGui.qApp, type(None)):
    app = QApplication([])
else:
    app = QtGui.qApp


class TestDefaultAuthenticationBoardAndSubtractorcodesModule(
    unittest.TestCase
):
    """TestCase for AuthenticationBoardModule and SubtractorcodesModule.

    Both modules inherit from CodeTableBase. Therefore, only
    AuthenticationBoardModule is used to test mutual functions.
    Module-specific functionality-tests are, of course, executed.
    """

    def setUp(self):
        """Create new AuthenticationBoardModule."""

        def press_enter_on_active_dialog():
            active_widget = app.activeModalWidget()
            QTest.keyClick(active_widget, Qt.Key_Enter)

        QTimer.singleShot(0, press_enter_on_active_dialog)
        self.authentication = AuthenticationBoardModule()

        QTimer.singleShot(0, press_enter_on_active_dialog)
        self.subtractor = SubtractorcodesModule()

    def test_default_module(self):
        """Test that module is initialized properly."""
        # Assert correct headline
        self.assertTrue(
            HEADLINE_TEXT_AUTHENTICATION
            in self.authentication.item(0, 0).text()
        )
        self.assertEqual(
            self.subtractor.item(0, 0).text(), HEADLINE_TEXT_SUBTRACTOR
        )

        # Assert correct number of rows including header
        self.assertEqual(
            self.authentication.rowCount(),
            START_NO_OF_CODES_AUTHENTICATION + 1,
        )
        self.assertEqual(
            self.subtractor.rowCount(), START_NO_OF_CODES_SUBTRACTOR + 1,
        )
        # Assert correct number of columns
        self.assertEqual(self.authentication.columnCount(), 3)
        self.assertEqual(self.subtractor.columnCount(), 3)

        # Assert cell content in first and second column is correct
        # From 1 to skip headline-row
Anders H. Rebner's avatar
Anders H. Rebner committed
        for i in range(1, 3):
            self.assertEqual(
                self.authentication.item(i, 0).text(),
                ROW_IDENTIFIERS_AUTHENTICATION[i - 1],
            )
            self.assertEqual(
                self.authentication.item(i, 1).text(), str(i - 1),
            )

            self.assertEqual(
                self.subtractor.item(i, 0).text(),
                ROW_IDENTIFIERS_SUBTRACTOR[i - 1],
            )

        # Assert cell content in third column is correct
        code = self.authentication.item(1, 2).text()
        self.assertTrue(len(code) >= CODE_LENGTH_AUTHENTICATION)
        # Assert all code characters are taken from list code_characters
        for _, character in enumerate(code):
            if character != " ":
                self.assertTrue(
                    character in self.authentication.code_characters
                )
        code = self.subtractor.item(1, 2).text()
        self.assertTrue(len(code) >= CODE_LENGTH_SUBTRACTOR)
        # Assert all code characters are digits
        for _, character in enumerate(code):
            if character != " ":
                self.assertTrue(character in string.digits)

        # Assert all codes are unique
        code_list = self.authentication.get_codes()
        code_set = set(code_list)
        self.assertEqual(len(code_list), len(code_set))

    def test_generate_unique_authentication_code(self):
        """Test function generate_unique_authentication_module."""
        code_list = self.authentication.get_codes()
        generated_code = self.authentication.generate_unique_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.authentication.get_codes()

        # Assert codes are correct
        for i, code in enumerate(code_list):
            self.assertEqual(code, self.authentication.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.authentication.show()
        QTest.qWaitForWindowExposed(self.authentication)

        # From experience it can happen that the widget is not fully
        # initialized before the QTest.keyClicks below. By calling
        # processEvents here we give Qt the opportunity to catch up with us
        app.processEvents()

        old_row_count = self.authentication.rowCount()

        # Use shortcut 'Ctrl + +'
        QTest.keyClicks(self.authentication, "+", Qt.ControlModifier)

        # Assert a new row is added
        new_row_count = self.authentication.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.authentication.item(row_index, 0).text(),
            ROW_IDENTIFIERS_AUTHENTICATION[row_index - 1],
        )
        self.assertEqual(self.authentication.item(row_index, 1).text(), "")
        new_code = self.authentication.item(row_index, 2).text()
        existing_code = self.authentication.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.authentication.show()
        QTest.qWaitForWindowExposed(self.authentication)

        # From experience it can happen that the widget is not fully
        # initialized before the QTest.keyClicks below. By calling
        # processEvents here we give Qt the opportunity to catch up with us
        app.processEvents()

        old_row_count = self.authentication.rowCount()

        # User should not be able to delete headline-row with shortcut
        # Locate headline-item, move mouse and and click (select) item
        item_center = self.authentication.visualItemRect(
            self.authentication.item(0, 0)
        ).center
        viewport = self.authentication.viewport()
        QTest.mouseMove(viewport, item_center())
        QTest.mouseClick(viewport, Qt.LeftButton, Qt.NoModifier, item_center())

        # Try to delete row with shortcut
        QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)

        # Assert row was not removed
        new_row_count = self.authentication.rowCount()
        self.assertEqual(old_row_count, new_row_count)

        # Move to first row (below headline), then use shortcut to delete it
        QTest.keyClick(self.authentication, Qt.Key_Down)
        value_to_delete = self.authentication.item(1, 1).text()
        QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)
        # Assert row was removed and replaced by the row below
        new_row_count = self.authentication.rowCount()
        self.assertEqual(old_row_count - 1, new_row_count)
        self.assertEqual(
            self.authentication.item(1, 1).text(), value_to_delete
        )

        # Remove rows until only headline-row and two code-rows exist
        for _ in range(1, self.authentication.rowCount()):
            QTest.keyClick(self.authentication, Qt.Key_Down)
            QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)
        self.assertTrue(self.authentication.rowCount() == 3)
        # Try to remove final code-row, should not work
        QTest.keyClick(self.authentication, Qt.Key_Down)
        QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)
        # Assert row was not removed
        self.assertTrue(self.authentication.rowCount() == 3)

    def test_add_to_soi_smoke_test(self):
        """Test that module can be added to SOI."""
        soi = SOI()
        authentication_name = "Test name"
        soi.add_module(authentication_name, self.authentication)
        self.assertTrue(soi.module_name_taken(authentication_name))


class TestAuthenticationBoardModuleFromData(unittest.TestCase):
    """TestCase for initializing AuthenticationBoardModule from data."""

    def test_create_from_data(self):
        """Test creating AuthenticationBoardModule from data."""
        test_data = {
            "cells": [
                "Headline text",
                ["A", "0", "TEST CODE ONE"],
                ["B", "1", "TEST CODE TWO"],
            ],
            "code_length": 11,
            "space_interval": 4,
            "space_amount": 1,
            "code_character_type": "ascii",
        }
        test_size = {"width": 100, "height": 100}

        module = AuthenticationBoardModule(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")