def getDataFromFile(file_name):
    """
    :param file_name: a file with data for test case. Usually a file name consists a name of test_function
    :return: data(list) with rows from a file except the first row
    """
    data = []
    log = logTestExecution()
    with open(file_name) as f:
        reader = csv.reader(f, delimiter=';')
        next(f)  # skip the first row
        try:
            for row in reader:
                data.append(row)
        except csv.Error as e:
            log.error('File {}, line {}: {}'.format(file_name, reader.line_num, e))
            sys.exit('File {}, line {}: {}'.format(file_name, reader.line_num, e))
    log.info('Got data <{}> from file <{}>'.format(data, file_name))
    return data
Esempio n. 2
0
class TestLoginPage(unittest.TestCase):
    log = logTestExecution()

    # The function defines LoginPage-instance and get the url. Ran before each test case
    @pytest.fixture(autouse=True)
    def classSetUp(self, setUp_and_tearDown):
        self.login_page = LoginPage(self.driver)
        self.driver.get(self.login_page.url)
        self.log.info('Testing the method of class: TestLoginPage')

    # Got and unpacked values (username, password, expected_message) to feed to the test from a file.
    @data(*getDataFromFile('GUI/test_login_failure_func.csv'))
    @unpack
    # Test different combinations of invalid credentials and error messages
    def test_login_failure(self, username, password, expected):
        self.login_page.login_button.click()
        result = self.login_page.loginIsNotValid(username, password, expected)
        assert result == True
        self.driver.refresh()

    def test_title(self):
        result = self.login_page.titleIsValid()
        assert result == True
class MainPage:
    log = logTestExecution()

    def __init__(self, driver):
        self.driver = driver

    @property
    def url(self):
        return 'https://www.southwest.com/'

    @property
    def get_depart_input(self):
        waits.wait_visibility(self.driver, MainPageLocators.DEPART_INPUT)
        return self.driver.find_element(*MainPageLocators.DEPART_INPUT)

    @property
    def get_destination_input(self):
        waits.wait_visibility(self.driver, MainPageLocators.DESTINATION_INPUT)
        return self.driver.find_element(*MainPageLocators.DESTINATION_INPUT)

    @property
    def get_book_element(self):
        waits.wait_visibility(self.driver, MainPageLocators.BOOK_ELEMENT)
        return self.driver.find_element(*MainPageLocators.BOOK_ELEMENT)

    @property
    def get_language_switcher(self):
        waits.wait_click(self.driver, MainPageLocators.LANGUAGE_SWITCHER)
        return self.driver.find_element(*MainPageLocators.LANGUAGE_SWITCHER)

    @property
    def get_hint_depart(self):
        waits.wait_visibility(self.driver, MainPageLocators.HINT_DEPART)
        return self.driver.find_element(*MainPageLocators.HINT_DEPART)

    @property
    def get_hint_destination(self):
        waits.wait_visibility(self.driver, MainPageLocators.HINT_DESTINATION)
        return self.driver.find_element(*MainPageLocators.HINT_DESTINATION)

    @property
    def get_hint_depart_options(self):
        menu = self.get_hint_depart
        waits.wait_visibility(self.driver, MainPageLocators.LI_TAGS)
        return menu.find_elements(*MainPageLocators.LI_TAGS)

    @property
    def get_menu_destination_options(self):
        menu = self.get_hint_destination
        waits.wait_visibility(self.driver, MainPageLocators.LI_TAGS)
        return menu.find_elements(*MainPageLocators.LI_TAGS)

    def get_control_messages(self):
        waits.wait_visibility(self.driver, MainPageLocators.CONTROL_MESSAGE)
        messages_list = self.driver.find_elements(
            *MainPageLocators.CONTROL_MESSAGE)
        self.log.info([message.text for message in messages_list])
        return messages_list

    def clear_inputs(self):
        # Clear inputs for departure and destination airport
        depart = self.get_depart_input
        depart.send_keys(Keys.CONTROL + "a")
        depart.send_keys(Keys.DELETE)

        destination = self.get_destination_input
        destination.send_keys(Keys.CONTROL + "a")
        destination.send_keys(Keys.DELETE)

    def size_element(self, element):
        # DIV_LIST = [HEADER_DIV, NAVIGATION_DIV, CONTACT_DIV, FOOTER_DIV, COPYRIGHT_DIV
        if element == 'HEADER_DIV':
            waits.wait_visibility(self.driver, MainPageLocators.HEADER_DIV)
            return self.driver.find_element(
                *MainPageLocators.HEADER_DIV).size['width'] > 0
        elif element == 'NAVIGATION_DIV':
            waits.wait_visibility(self.driver, MainPageLocators.NAVIGATION_DIV)
            return self.driver.find_element(
                *MainPageLocators.NAVIGATION_DIV).size['width'] > 0
        elif element == 'CONTACT_DIV':
            waits.wait_visibility(self.driver, MainPageLocators.CONTACT_DIV)
            return self.driver.find_element(
                *MainPageLocators.CONTACT_DIV).size['width'] > 0
        elif element == 'FOOTER_DIV':
            waits.wait_visibility(self.driver, MainPageLocators.FOOTER_DIV)
            return self.driver.find_element(
                *MainPageLocators.FOOTER_DIV).size['width'] > 0
        elif element == 'COPYRIGHT_DIV':
            waits.wait_visibility(self.driver, MainPageLocators.COPYRIGHT_DIV)
            return self.driver.find_element(
                *MainPageLocators.COPYRIGHT_DIV).size['width'] > 0

    def allElementsPresence(self):
        """
        Check that the main blocks (header, footer, contacts, etc.) on the website are present, visible
        and with width > 0
        :return: True if all the elements are found
        """
        # DIV_LIST = [HEADER_DIV, NAVIGATION_DIV, CONTACT_DIV, FOOTER_DIV, COPYRIGHT_DIV
        elements = MainPageLocators.DIV_LIST
        for element in elements:
            try:
                result = self.size_element(element)
                if result is True:
                    self.log.info(
                        'DIV element <{}> found successfully with width > 0'.
                        format(element))
                    return True
                else:
                    self.log.error(
                        'DIV element <{}> NOT found'.format(element))
                    return False
            except:
                self.log.error('DIV element <{}> NOT found'.format(element))
                return False

    def languageSwitch(self):
        """
        :return: True if button to switch a language are clicked
        """
        try:
            switcher = self.get_language_switcher
            self.log.info('<language_switcher> found')
            switcher.click()
            self.log.info('Clicked SUCCESSFULLY')
            return True
        except:
            self.log.error('<language_switcher> NOT clickable')
            return False

    def getValue_LangAttribute(self, expected_value):
        """        
        :param expected_value: EN or ES
        :return: True if expected_value == value of the lang-attribute of the <html>-tag
        """
        if expected_value.lower() == 'es':
            try:
                waits.wait_title(self.driver, MainPageLocators.TITLE_ES)
                waits.wait_visibility(self.driver, MainPageLocators.HTML_TAG)
                html_tag = self.driver.find_element(*MainPageLocators.HTML_TAG)
                lang_value = html_tag.get_attribute('lang')
                self.log.info(
                    'Value of the attribute @lang = {}'.format(lang_value))
                if lang_value.lower() == expected_value.lower():
                    self.log.info(
                        'Expected value <{}> for property @lang for tag <html> found'
                        .format(expected_value))
                    return True
            except:
                self.log.error(
                    'Expected value <{}> for property @lang for tag <html> NOT found'
                    .format(expected_value))
                return False
        elif expected_value.lower() == 'en':
            try:
                waits.wait_title(self.driver, MainPageLocators.TITLE_EN)
                waits.wait_visibility(self.driver, MainPageLocators.HTML_TAG)
                html_tag = self.driver.find_element(*MainPageLocators.HTML_TAG)
                lang_value = html_tag.get_attribute('lang')
                self.log.info(
                    'Value of the attribute @lang = {}'.format(lang_value))
                if lang_value.lower() == expected_value.lower():
                    self.log.info(
                        'Expected value <{}> for property @lang for tag <html> found'
                        .format(expected_value))
                    return True
            except:
                self.log.error(
                    'Expected value <{}> for property @lang for tag <html> NOT found'
                    .format(expected_value))
                return False
        else:
            self.log.error(
                'Expected value is not expected'.format(expected_value))
            return False

    def get_attributes_depart(self):
        '''
        Check that the departure-input has attributes "aria-activedescendant" and "aria-expanded".
        Then check their expected values. The attributes are responsible for appearing the menu with hints.
        :return: True if the expected attributes and their values have been found
        '''
        # ATTRIBUTES = {"aria-activedescendant": "LandingAirBookingSearchForm", "aria-expanded": "true"}
        attributes = MainPageLocators.ATTRIBUTES
        self.log.info('Attribute: value to check {}'.format(attributes))
        try:
            for k in attributes.keys():
                if attributes[k] in self.get_depart_input.get_attribute(k):
                    self.log.info('Value <{}> in attribute <{}> found'.format(
                        attributes[k], k))
                else:
                    self.log.error(
                        'Value <{}> in attribute <{}> NOT found'.format(
                            attributes[k], k))
                    return False
            return True
        except:
            self.log.error('Wrong attributes or their values')
            return False

    def get_attributes_destination(self):
        '''
        Check that the destination-input has attributes "aria-activedescendant" and "aria-expanded".
        Then check their expected values. The attributes are responsible for appearing the menu with hints.
        :return: True if the expected attributes and their values have been found
        '''
        # ATTRIBUTES = {"aria-activedescendant": "LandingAirBookingSearchForm", "aria-expanded": "true"}
        attributes1 = MainPageLocators.ATTRIBUTES
        self.log.info('Attribute: value to check {}'.format(attributes1))
        try:
            for k in attributes1.keys():
                if attributes1[k] in self.get_destination_input.get_attribute(
                        k):
                    self.log.info('Value <{}> in attribute <{}> found'.format(
                        attributes1[k], k))
                else:
                    self.log.error(
                        'Value <{}> in attribute <{}> NOT found'.format(
                            attributes1[k], k))
                    attributes1.clear()
                    return False
            return True
        except:
            self.log.error('Wrong attributes or their values')
            return False

    def listingDepartIsEnable(self):
        """
        Check that the menu with hints for the departure-input has an arrow to move up and down
        if hints are more than 10.
        :return: True if hints are more than 10 and there are arrows to move up and down
        """
        try:
            list = self.get_hint_depart_options
            if len(list) > 10:
                self.driver.find_element(
                    *MainPageLocators.MOVE_DOWN).is_enabled()
                self.log.info('Element <{}> found'.format(
                    MainPageLocators.MOVE_DOWN))
                self.driver.find_element(*MainPageLocators.MOVE_UP)
                self.log.info('Element <{}> found'.format(
                    MainPageLocators.MOVE_UP))
                return True
            else:
                self.log.warning(
                    'Listing is unable: not enough options (< 10)')
                return False
        except:
            self.log.error('Listing NOT found')
            return False

    def listingDestinationIsEnable(self):
        """
        Check that the menu with hints for the destination-input has an arrow to move up and down
        if hints are more than 10.
        :return: True if hints are more than 10 and there are arrows to move up and down
        """
        try:
            list1 = self.get_menu_destination_options
            if len(list1) > 10:
                self.driver.find_element(
                    *MainPageLocators.MOVE_DOWN).is_enabled()
                self.log.info('Element <{}> found'.format(
                    MainPageLocators.MOVE_DOWN))
                self.driver.find_element(*MainPageLocators.MOVE_UP)
                self.log.info('Element <{}> found'.format(
                    MainPageLocators.MOVE_UP))
                return True
            else:
                self.log.warning(
                    'Listing is unable: not enough options (< 10)')
                return False
        except:
            self.log.error('Listing NOT found')
            return False

    @property
    def listEnableButtonsDepart(self):
        """
        Find the menu with hints for the departure-input.
        Then find the list of enable hints (buttons) to click
        :return: the list of the buttons which are enabled to click
        """
        menu = self.get_hint_depart
        buttons = menu.find_elements(*MainPageLocators.OPTIONS)
        enabled_buttons = [button for button in buttons if button.is_enabled()]
        self.log.info('{} buttons to click found'.format(len(enabled_buttons)))
        return enabled_buttons

    # Before click
    def getValue_AriaLabelAttr(self, position):
        """
        Find enable buttons to click in a menu for the departure-input and get the value of the attribute 'aria-label'
        for the button on the pointed <position>.
        :param: position to get an attribute value
        :return: value of the attribute 'aria-label' (text of the button on the pointed <position>).
        If <position> is out of range or smt goes wrong the function return value = '$$$' but not None
        to avoid an error in a test case
        """
        position = int(position)
        button_list = self.listEnableButtonsDepart
        if len(button_list) > position:
            try:
                value = button_list[position].get_attribute(
                    'aria-label')  # 'aria-label' contains the button's text
                self.log.info(
                    'Attribute value (text) found: <{}>'.format(value))
            except:
                value = '$$$'
                self.log.error("Attribute NOT found.")
        else:
            value = '$$$'
            self.log.error(
                "Available buttons NOT found on the {}-th position.".format(
                    position))
        return value

    def getEnableButtonClick(self, position):
        """
        Find enable buttons to click in a menu for the departure-input and click on the button on the pointed <position>
        :param: position to click
        :return: True if clicked successfully
        """
        position = int(position)
        button_list = self.listEnableButtonsDepart
        if len(button_list) > int(position):
            try:
                button = button_list[position]
                button.click()
                self.log.info(
                    "Click on {}-th button successfully".format(position))
                return True
            except:
                self.log.error("Click failed.")
                return False
        else:
            self.log.error(
                "Available buttons NOT found on the {}-th position.".format(
                    position))
            return False
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from GUI.configfiles.log_execution import logTestExecution

log = logTestExecution()


# Explicit wait (<=20 sec with polling every 1 sec) with expected_conditions: clickability of the element
def wait_click(driver, locator_name):
    try:
        wait = WebDriverWait(driver, 20)
        wait.until(expected_conditions.element_to_be_clickable(locator_name))
        log.info('Element {} is clickable'.format(locator_name))
    except TimeoutException:
        log.error('Element {} is not clickable'.format(locator_name))


# Explicit wait (<=20 sec with polling every 1 sec) with expected_conditions: visibility of the element
def wait_visibility(driver, locator_name):
    try:
        wait = WebDriverWait(driver, 20)
        wait.until(
            expected_conditions.visibility_of_element_located(locator_name))
        log.info('Element {} is visible'.format(locator_name))
    except TimeoutException:
        log.error('Element {} is not visible'.format(locator_name))


# Explicit wait (<=20 sec with polling every 1 sec) with expected_conditions: text in title
def wait_title(driver, text):
class LoginPage:
    log = logTestExecution()

    def __init__(self, driver):
        self.driver = driver

    @property
    def url(self):
        return 'https://www.southwest.com/'

    @property
    def login_button(self):
        waits.wait_click(self.driver, LoginPageLocators.LOGIN_BUTTON)
        return self.driver.find_element(*LoginPageLocators.LOGIN_BUTTON)

    @property
    def username_field(self):
        waits.wait_visibility(self.driver, LoginPageLocators.USERNAME_FIELD)
        return self.driver.find_element(*LoginPageLocators.USERNAME_FIELD)

    @property
    def password_field(self):
        waits.wait_visibility(self.driver, LoginPageLocators.PASSWORD_FIELD)
        return self.driver.find_element(*LoginPageLocators.PASSWORD_FIELD)

    @property
    def submit_button(self):
        waits.wait_visibility(self.driver, LoginPageLocators.SUBMIT)
        return self.driver.find_element(*LoginPageLocators.SUBMIT)

    @property
    def get_title(self):
        return self.driver.title

    @property
    def error_messages(self):
        waits.wait_visibility(self.driver,
                              LoginPageLocators.ERROR_MESSAGE_LOCATOR)
        return self.driver.find_elements(
            *LoginPageLocators.ERROR_MESSAGE_LOCATOR)

    def titleIsValid(self):
        try:
            if LoginPageLocators.TITLE in self.get_title:
                self.log.info('The title <{}> found'.format(self.get_title))
                return True
            else:
                self.log.error('The WRONG title <{}> found'.format(
                    self.get_title))
                return False
        except:
            self.log.error('The title NOT found')
            return False

    def login(self, username, password):
        self.username_field.send_keys(username)
        self.log.info('Use username = {}'.format(username))
        self.password_field.send_keys(password)
        self.log.info('Use password = {}'.format(password))
        self.submit_button.click()

    def loginIsNotValid(self, username, password, expected):
        """
        :param username, password
        :param expected: message that is expected to see after entering and submitting login and password
        :return: True if inputs for username/password are found, data are submitted and expected messages are found
        """
        try:
            self.login(username, password)
            for message in self.error_messages:
                if (expected[0] in message.text) or (expected[1]
                                                     in message.text):
                    self.log.info('The expected message <{}> found'.format(
                        message.text))
                    return True
                else:
                    self.log.error(
                        'The expected message <{}> NOT found'.format(
                            message.text))
                    return False
        except:
            self.log.error(
                'Something is wrong during attempting to fail the login with invalid username <{}> and '
                'password <{}>'.format(username, password))
            return False
Esempio n. 6
0
class TestMainPage(unittest.TestCase):
    log = logTestExecution()

    # The function defines MainPage-instance and get the url. Ran before each test case
    @pytest.fixture(autouse=True)
    def classSetUp(self, setUp_and_tearDown):
        self.page = MainPage(self.driver)
        # Used to make a few assertions in one test case w/o failure in the middle one.
        self.soft_assert = SoftAssertion(self.driver)
        self.driver.get(self.page.url)
        self.log.info('Testing the method of class: TestMainPage')

    # The presence of the main blocks: ['HEADER_DIV', 'NAVIGATION_DIV', 'CONTACT_DIV', 'FOOTER_DIV', 'COPYRIGHT_DIV']
    def test_element_presence(self):
        result = self.page.allElementsPresence()
        assert result == True

    # Used softAssertion to test switching a language
    # click on "Español", check the attribute in <html>-tag, the current url,  key-words on the page
    def test_EN_to_ES(self):
        result = self.page.languageSwitch()
        self.soft_assert.assert_it(result, 'Language switched (EN to ES)')

        result2 = self.page.getValue_LangAttribute('ES')
        self.soft_assert.assert_it(result2, 'Language property in DOM found')

        result3 = 'reservar' in self.page.get_book_element.text.lower()
        self.soft_assert.assert_it(result3, 'Book-element found')

        result4 = 'english' in self.page.get_language_switcher.text.lower()
        self.soft_assert.assert_it(result4, "Button's text switched")

        result5 = 'espanol' in self.driver.current_url
        self.soft_assert.assert_last(result5, 'Current URL verified')

    # Used softAssertion to test switching a language
    # click on "Español" and back to "English", check the <html>-tag's attribute, the current url, key-words
    def test_ES_to_EN(self):
        result = self.page.languageSwitch()
        self.soft_assert.assert_it(result, 'Language switched (EN to ES)')
        # Test doesn't work w/o it (although there is explicit wait).
        # I don't know why, but it's easier leave it than spend 2 more hours to investigate.
        time.sleep(2)

        result2 = self.page.languageSwitch()
        self.soft_assert.assert_it(result2, 'Language switched (ES to EN)')

        result3 = self.page.getValue_LangAttribute('EN')
        self.soft_assert.assert_it(result3, 'Language property in DOM found')

        result4 = 'book' in self.page.get_book_element.text.lower()
        self.soft_assert.assert_it(result4, 'Book-element found')

        result5 = 'español' in self.page.get_language_switcher.text.lower()
        self.soft_assert.assert_it(result5, "Button's text switched")

        result6 = 'espanol' not in self.driver.current_url
        self.soft_assert.assert_last(result6, 'Current URL verified')

    def test_hint_appearance_depart(self):
        depart_port = 'new'
        # Find the departure input and enter data
        depart = self.page.get_depart_input
        depart.send_keys(depart_port)

        # The <input>-tag get the attributes that are responsible for the menu with hints
        result = self.page.get_attributes_depart()
        self.soft_assert.assert_it(result,
                                   'Attributes for departure input found')

        # Find the menu-element
        result2 = self.page.get_hint_depart is not None
        self.soft_assert.assert_last(result2, 'Hint for departure form found')

        self.page.clear_inputs()

    def test_hint_appearance_destination(self):
        destin_port = 'wash'
        # Find the destination input and enter data
        destination = self.page.get_destination_input
        destination.send_keys(destin_port)
        # The <input>-tag get the attributes that are responsible for the menu with hints
        result = self.page.get_attributes_destination()
        self.soft_assert.assert_it(result,
                                   'Attributes for destination input found')
        # Find the menu-element
        result2 = self.page.get_hint_destination is not None
        self.soft_assert.assert_last(result2,
                                     'Hint for destination form found')

        self.page.clear_inputs()

    # This one is unstable: sometimes a destination menu covers very quick (mouse hover and time.sleep don't help)
    def test_hint_listing(self):
        depart_port = 'new'
        destin_port = 'san'
        # Find the departure input and enter data
        depart = self.page.get_depart_input
        depart.send_keys(depart_port)
        # Menu appears with > 10 options and buttons to move up and down
        result = self.page.listingDepartIsEnable()
        self.soft_assert.assert_it(result,
                                   'Listing elements in departure hint found')
        # Find the destination input and enter data
        destin = self.page.get_destination_input
        destin.send_keys(destin_port)
        # Menu appears with > 10 options and buttons to move up and down
        result2 = self.page.listingDestinationIsEnable()
        self.soft_assert.assert_last(
            result2, 'Listing elements in destination hint found')

        self.page.clear_inputs()

    # Got and unpacked values (depart_text, position, expected_depart_text) to feed to the test from a file.
    @data(*getDataFromFile('GUI/test_choose_hint_option_depart_func.csv'))
    @unpack
    def test_choose_hint_option_depart(self, depart_text, position,
                                       expected_depart_text):
        # Find the departure input and enter data
        depart = self.page.get_depart_input
        depart.send_keys(depart_text)
        # Before click
        # Get the value of the attribute 'aria-label' for the button(button's text) we are going to click further
        valueAriaLabelAttr = self.page.getValue_AriaLabelAttr(position)
        # Then click
        result = self.page.getEnableButtonClick(position)
        self.soft_assert.assert_it(result, 'Click on the button occurred')
        # After click
        # Get the texts of control messages (under an input)
        control_messages = self.page.get_control_messages()
        # Apply a soft assertion to check that texts in input and under it are the same
        result2 = control_messages[
            0].text in valueAriaLabelAttr  # 0-th element for departure, 1-th for destination
        self.soft_assert.assert_it(
            result2,
            'Control message <{}> found in button attribute value <{}>'.format(
                control_messages[0].text, valueAriaLabelAttr))
        # Apply a soft assertion to check that control messages are equal to expected one.
        result3 = expected_depart_text in control_messages[0].text
        self.soft_assert.assert_last(
            result3, 'Expected text <{}> found in control massage <{}>'.format(
                expected_depart_text, control_messages[0].text))

        self.page.clear_inputs()