class CheckPoint(unittest.TestCase):
    def __init__(self):
        """
        Inits CheckPoint class

        Required Parameters:
            None

        Optional Parameters:
            None

        Returns:
            None
        """
        super(CheckPoint, self).__init__()
        self.statusMap = {}
        self.util = Util()
        self.log = cl.customLogger()

    def setStatus(self, key, value):
        """
        Set status of the map which keeps track of the verification points

        Required Parameters:
            key: <Test Name>.<Result Message>
            value: Test Result (Pass / Fail)

        Optional Parameters:
            None

        Returns:
            None
        """
        self.statusMap[key] = value

    def clearStatus(self):
        """
        Clear status of the map which keeps track of the verification points

        Required Parameters:
            None

        Optional Parameters:
            None

        Returns:
            None
        """
        self.statusMap.clear()
        self.log.info("Clear result status of previous test")

    def mark(self, testName, result, resultMessage):
        """
        Mark the result of the verification point in a test case

        Required Parameters:
            testName: Name of the test case
            result: Result of the test case (Boolean)
            resultMessage: Result message that needs to be logged

        Optional Parameters:
            None

        Returns:
            None
        """
        testName = testName.lower()
        mapKey = testName + "." + resultMessage
        try:
            if result:
                self.setStatus(mapKey, "PASS")
                self.log.info("Verification successful :: " + resultMessage)
            else:
                self.setStatus(mapKey, "FAIL")
                self.util.screenShot("FAIL" + mapKey)
                self.log.info("Verification failed :: " + resultMessage)
        except:
            self.log.info("### Exception Occurred !!!")
            self.setStatus(mapKey, "FAIL")
            traceback.print_stack()

    def markFinal(self, testName, result, resultMessage):
        """
        Mark the final result of the verification point in a test case
        This needs to be called at least once in a test case
        This should be final checkPoint of the test case

        Required Parameters:
            testName: Name of the test case
            result: Result of the test case (Boolean)
            resultMessage: Result message that needs to be logged

        Optional Parameters:
            None

        Returns:
            None
        """
        testName = testName.lower()
        mapKey = testName + "." + resultMessage
        try:
            if result is not None:
                if result:
                    self.setStatus(mapKey, "PASS")
                    self.log.info("### VERIFICATION SUCCESSFUL :: " +
                                  resultMessage)
                else:
                    self.setStatus(mapKey, "FAIL")
                    self.util.screenShot("FAIL" + mapKey)
                    self.log.error("### VERIFICATION FAILED :: " +
                                   resultMessage)
            else:
                self.setStatus(mapKey, "FAIL")
                self.log.error("### Exception Occurred, Result is None !!!")
                self.log.error("### VERIFICATION FAILED :: " + resultMessage)
                self.log.error("Result value :: " + str(result))
        except:
            self.setStatus(mapKey, "FAIL")
            self.log.error("### Exception Occurred !!!")
            self.util.screenShot("FAIL" + mapKey)
            traceback.print_stack()

        resultList = []
        for key in self.statusMap:
            resultList.append(self.statusMap[key])
            self.log.info(self.statusMap[key] + " :: " + key)

        if "FAIL" in resultList:
            self.log.error(testName + " ### TEST FAILED")
            self.assertTrue(False)
        else:
            self.log.info(testName + " ### TEST SUCCESSFUL")
            self.assertTrue(True)
class BasePage(SeleniumDriver):
    def __init__(self, driver):
        """
        Inits BasePage class

        Required Parameters:
            driver: WebDriver Object

        Optional Parameters:
            None

        Returns:
            None
        """
        super(BasePage, self).__init__(driver)
        self._validate_page(driver)
        self.driver = driver
        self.util = Util()
        self.bkend = BEConnection()

    def verifyFlashMessage(self, textToVerify, timeout=6):
        """
        Validate the flash message after completing an action

        Required Parameters:
            textToVerify: Text on the flash message that needs to be verified

        Optional Parameters:
            None

        Returns:
            Boolean
        """
        try:
            flashMessageElement = self.waitForElement(
                locator=".nmbl-flash-message-content",
                locatorType="css",
                info="flash message",
                timeout=timeout)
            if flashMessageElement is not None:
                elementText = self.getText(flashMessageElement,
                                           "Getting text on flash message")
                # elementText = self.getText(self.getElementByClassName("flash-message"),
                #                            "Getting text on flash message")
                result = self.util.verifyTextContains(elementText,
                                                      textToVerify)
                # flashMessageClose = self.getElementByClassName("flash-message-close")
                flashMessageClose = self.getElementByCss(
                    ".nmbl-flash-message-close")
                self.clickElement(flashMessageClose,
                                  "Flash message 'X' close button", 1)
                return result
            else:
                # If element does not show up before timeout, return False
                return False
        except:
            self.log.error("Failed to get text on flash message")
            print_stack()
            return False

    def verifyModalMessage(self,
                           textToVerify,
                           textLocator,
                           buttonToClickLocator,
                           buttonInfo=""):
        """
        Validate the message on the modal and click Ok/Close button to close the modal

        Required Parameters:
            textToVerify: Text on the modal that needs to be verified
            textLocator: Locator of the message
            buttonToClickLocator: Locator of the button to click on modal

        Optional Parameters:
            None

        Returns:
            Boolean
        """
        try:
            result = False
            elementPresent = self.isElementPresent(textLocator)
            if elementPresent:
                elementText = self.getText(self.getElement(textLocator),
                                           "Getting text on modal")
                result = self.util.verifyTextContains(elementText,
                                                      textToVerify)
            if not result:
                self.util.screenShot("FAIL-Modal-Message-Verification")
            self.clickElement(self.getElement(buttonToClickLocator),
                              buttonInfo)
            return result
        except:
            self.log.error("Failed to get text on modal")
            print_stack()
            return False

    def verifyModalConfirmation(self, buttonLocator, info, locatorType="id"):
        """
        Verify the confirmation modal is present and click the 'Confirmation' button
        'Confirmation' button can be OK/Close/Delete

        Required Parameters:
            buttonLocator: Locator of the button on confirmation modal
            info: Information about the button, usually text on the button

        Optional Parameters:
            locatorType: Type of the locator(id(default), xpath, css, className, linkText)

        Returns:
            Boolean
        """
        try:
            elementPresent = self.isElementPresent(buttonLocator, locatorType)
            if elementPresent:
                return self.clickElement(self.getElement(buttonLocator), info)
            return False
        except:
            self.log.error("Failed to find button on confirmation modal")
            print_stack()
            return False

    def verifyFieldErrorMessage(self, locator, textToVerify, locatorType="id"):
        """
        Validate the flash message after completing an action

        Required Parameters:
            locator: Locator of the error message
            textToVerify: Text on the flash message that needs to be verified

        Optional Parameters:
            locatorType: Type of the locator, default is 'id'

        Returns:
            Boolean
        """
        try:
            elementPresent = self.isElementPresent(locator, locatorType)
            if elementPresent:
                elementText = self.getText(
                    self.getElement(locator),
                    "Getting text on field error message")
                result = self.util.verifyTextContains(elementText,
                                                      textToVerify)
                return result
            return False
        except:
            self.log.error("Failed to get text on field error message")
            print_stack()
            return False

    def verifyPageTitle(self, titleToVerify):
        """
        Verify the page Title

        Required Parameters:
            titleToVerify: Title on the page that needs to be verified

        Optional Parameters:
            None

        Returns:
            Boolean
        """
        try:
            actualTitle = self.getBrowserTitle()
            return self.util.verifyTextContains(actualTitle, titleToVerify)
        except:
            self.log.error("Failed to get page title")
            print_stack()
            return False

    @abstractmethod
    def _validate_page(self, driver):
        pass

    """ Regions define functionality available through all page objects """