<repo_name>reetambhowmick/py-test-auto-framework<file_sep>/AutomationPractice/registration_and_login/pom/page_authentication.py
from selenium.webdriver.support.select import Select

from AutomationPractice.registration_and_login.pom.base import BasePage
from AutomationPractice.registration_and_login.pom.locators import Locators


class AuthenticationPage(BasePage):
    """ Authentication Page Class
        It contains multiple sub section: Login, Create Account and Personal Info section as class composition
    """

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

        self.login_section = LoginSection(self)
        self.create_account_section = CreateAccountSection(self)
        self.personal_info_section = PersonalInfoSection(self)


class LoginSection:
    """ Login section """
    driver = None

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

        # Below is creating class attribute for each locator in Locator class as one Element object and one locator_* string
        for k, v in Locators.Authentication_login.items():
            setattr(self, k, self.page.com.element(v))
            setattr(self, "elem_ " + k, v)

    def input_email_address(self, email):
        self.textbox_email().send_keys(email)

    def input_password(self, password):
        self.textbox_password().send_keys(<PASSWORD>)

    def click_sign_in_button(self):
        self.button_sign_in().click()

    def perform_login(self, email, password, wait_for_next_page_load=True):
        self.input_email_address(email)
        self.input_password(<PASSWORD>)
        self.click_sign_in_button()
        if wait_for_next_page_load:
            self.page.wait_for_page_load("myaccountpage")

    def get_error_list(self):
        errors = [x.text for x in self.list_error_items(find_all=True)]
        return errors

    def is_login_error_occured(self):
        return (len(self.get_error_list()) > 0)


class CreateAccountSection:
    """ Create Account Section """

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

        # Below is creating class attribute for each locator in Locator class as one Element object and one locator_* string
        for k, v in Locators.Authentication_create_account.items():
            setattr(self, k, self.page.com.element(v))
            setattr(self, "elem_ " + k, v)

    def input_email_address(self, email):
        self.textbox_email().send_keys(email)

    def click_button_create_account(self, wait_for_next_page_load=True):
        self.button_create_account().click()
        if wait_for_next_page_load:
            self.page.wait_for_page_load("personalinfopage")


class PersonalInfoSection:
    """ Personal Info fields section"""

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

        # Below is creating class attribute for each locator in Locator class as one Element object and one locator_* string
        for k, v in Locators.Authentication_personal_info.items():
            setattr(self, k, self.page.com.element(v))
            setattr(self, "elem_ " + k, v)

    def get_section_heading(self):
        return self.subheadings().text

    def input_personal_info(self, fields_values):
        if "title" in fields_values:
            if fields_values["title"] == "mrs":
                self.field_option_title_Mrs().click()
            else:
                self.field_option_title_Mr().click()

        if "first_name" in fields_values:
            self.field_textbox_first_name().send_keys(fields_values["first_name"])
            # self.field_textbox_address_firstname().send_keys(fields_values["first_name"])

        if "last_name" in fields_values:
            self.field_textbox_last_name().send_keys(fields_values["last_name"])
            # self.field_textbox_address_lastname().send_keys(fields_values["last_name"])

        if "email" not in fields_values:
            if self.field_textbox_email().get_attribute('value'):
                self.field_textbox_email().clear()

        if "password" in fields_values:
            self.field_textbox_password().send_keys(fields_values["password"])

        if "dob_date" in fields_values:
            Select(self.field_select_dob_day()).select_by_value(str(fields_values["dob_date"]))

        if "dob_month" in fields_values:
            Select(self.field_select_dob_month()).select_by_value(str(fields_values["dob_month"]))

        if "dob_year" in fields_values:
            Select(self.field_select_dob_year()).select_by_value(str(fields_values["dob_year"]))

        if "company" in fields_values:
            self.field_textbox_address_company().send_keys(fields_values["company"])

        if "address1" in fields_values:
            self.field_textbox_address_address1().send_keys(fields_values["address1"])

        if "address2" in fields_values:
            self.field_textbox_address_address2().send_keys(fields_values["address2"])

        if "city" in fields_values:
            self.field_textbox_address_city().send_keys(fields_values["city"])

        if "state_index" in fields_values:
            Select(self.field_select_address_state()).select_by_value(str(fields_values["state_index"]))

        if "zipcode" in fields_values:
            self.field_textbox_address_postcode().send_keys(fields_values["zipcode"])

        if "additional_info" in fields_values:
            self.field_textbox_address_additionalinfo().send_keys(fields_values["additional_info"])

        if "home_phone" in fields_values:
            self.field_textbox_address_phone().send_keys(fields_values["home_phone"])

        if "mobile_phone" in fields_values:
            self.field_textbox_address_mobile().send_keys(fields_values["mobile_phone"])

        if "address_alias" in fields_values:
            el_ad_alias = self.field_textbox_address_alias()
            el_ad_alias.clear()
            el_ad_alias.send_keys(fields_values["address_alias"])
        else:
            el_ad_alias = self.field_textbox_address_alias()
            el_ad_alias.clear()

    def click_button_register(self, wait_for_next_page_load=True):
        self.button_register().click()
        if wait_for_next_page_load:
            self.page.wait_for_page_load("myaccountpage")

    def get_error_list(self):
        errors = [x.text for x in self.list_error_items(find_all=True)]
        return errors

    def is_login_error_occured(self):
        return (len(self.get_error_list()) > 0)
<file_sep>/AutomationPractice/registration_and_login/pom/locators.py
class Locators:
    Home = {
        'link_sign_in': 'css|a.login',
        'link_sign_out': 'css|a.logout'
    }

    Authentication_create_account = {
        'heading': 'tagname|h1',
        'subheading': 'css|form#create-account_form h3',
        'textbox_email': 'id|email_create',
        'button_create_account': 'id|SubmitCreate',
        'list_error_items': 'css|#create_account_error>ol>li'
    }

    Authentication_login = {
        'heading': 'tagname|h1',
        'subheadings': 'css|form#login_form h3',
        'textbox_email': 'id|email',
        'textbox_password': '<PASSWORD>',
        'button_sign_in': 'id|SubmitLogin',
        'list_error_items': 'css|div.center_column> :nth-child(2)>ol>li'
    }

    Authentication_personal_info = {
        'heading': 'tagname|h1',
        'subheadings': 'tagname|h3',
        'div_account_creation': 'css|div.account_creation',
        'field_option_title_Mr': 'id|uniform-id_gender1',
        'field_option_title_Mrs': 'id|uniform-id_gender2',
        'field_textbox_first_name': 'id|customer_firstname',
        'field_textbox_last_name': 'id|customer_lastname',
        'field_textbox_email': 'id|email',
        'field_textbox_password': '<PASSWORD>',
        'field_select_dob_day': 'id|days',
        'field_select_dob_month': 'id|months',
        'field_select_dob_year': 'id|years',
        'field_checkbox_newsletter': 'id|uniform-newsletter',
        'field_checkbox_offers': 'id|uniform-optin',
        'field_textbox_address_firstname': 'id|firstname',
        'field_textbox_address_lastname': 'id|lastname',
        'field_textbox_address_company': 'id|company',
        'field_textbox_address_address1': 'id|address1',
        'field_textbox_address_address2': 'id|address2',
        'field_textbox_address_city': 'id|city',
        'field_select_address_state': 'id|id_state',
        'field_textbox_address_postcode': 'id|postcode',
        'field_select_address_country': 'id|id_country',
        'field_textbox_address_additionalinfo': 'id|other',
        'field_textbox_address_phone': 'id|phone',
        'field_textbox_address_mobile': 'id|phone_mobile',
        'field_textbox_address_alias': 'id|alias',
        'field_textbox_tax_idno': 'id|dni',
        'list_error_items': 'css|.alert-danger>ol>li',
        'button_register': 'id|submitAccount'
    }

    Myaccount = {
        'heading': 'tagname|h1',
        'link_account': 'css|a.account'
    }
<file_sep>/AutomationPractice/registration_and_login/pom/base.py
"""
This is base page to handle common elements,methods across the pages.
"""

from selenium.common.exceptions import ElementNotVisibleException

from core.com import Com
from AutomationPractice.registration_and_login.pom.locators import Locators


class BasePage(object):
    """ This is Base Page class. For all common properties and methods. All page classes inherit this class."""
    driver = None
    Locators = Locators

    def __init__(self, driver):
        BasePage.driver = driver
        self.com = Com(driver)

    def open_url(self, url):
        self.driver.get(url)

    def close(self):
        BasePage.driver.close()

    def quit(self):
        BasePage.driver.quit()

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

    def get_page_h1_heading_text(self):
        return self.com.findElement(self.Locators.Authentication_personal_info['heading']).text

    def wait_for_page_load(self, page_name):
        try:
            if page_name == "homepage":
                self.com.wait.wait_for_element_visible(self.Locators.Home["link_sign_in"])
            elif page_name == "loginpage" or page_name == "createaccount":
                self.com.wait.wait_for_element_visible(self.Locators.Authentication_create_account["subheading"])
            elif page_name == "personalinfopage":
                self.com.wait.wait_for_element_with_text_present(
                    self.Locators.Authentication_personal_info['subheadings'], "YOUR PERSONAL INFORMATION")
            elif page_name == "myaccountpage":
                self.com.wait.wait_for_element_visible(self.Locators.Myaccount["link_account"])
            else:
                raise Exception("Incorrect Page Name passed")
        except ElementNotVisibleException as e:
            print(e)
            raise Exception("Page {} is unable to load".format(page_name))
<file_sep>/AutomationPractice/registration_and_login/tests/test_registration.py
import time

import pytest
from AutomationPractice.registration_and_login.testdata.test_data_provider import TestDataProvider


class TestRegistration:


    @pytest.mark.positive
    @pytest.mark.parametrize("new_user_data",
                             TestDataProvider.generate_user_reg_data(save_user=True))
    def test_registration_success_scenario(self, app, new_user_data):
        # TestDataProvider.save_created_account(new_user_data["email"], new_user_data["password"])
        app.home_page.open_homepage()
        app.home_page.click_sign_in()
        app.authentication_page.create_account_section.input_email_address(new_user_data["email"])
        app.authentication_page.create_account_section.click_button_create_account()
        actual = app.authentication_page.get_page_h1_heading_text()
        pytest.assume("CREATE AN ACCOUNT" == actual, "Actual:{} ,Expected: {}".format(actual, "CREATE AN ACCOUNT"))
        actual = app.authentication_page.personal_info_section.get_section_heading()
        pytest.assume("YOUR PERSONAL INFORMATION" == actual,
                      "Actual:{} ,Expected: {}".format(actual, "YOUR PERSONAL INFORMATION"))

        app.authentication_page.personal_info_section.input_personal_info(new_user_data)
        app.authentication_page.personal_info_section.click_button_register()
        title = app.authentication_page.get_title()
        expected_title = "My account - My Store"
        pytest.assume(title == expected_title, "Actual:{} ,Expected: {}".format(title, expected_title))
        full_name = app.myaccount_page.get_logged_in_full_name()
        expected_full_name = new_user_data["first_name"] + " " + new_user_data["last_name"]
        pytest.assume(full_name == expected_full_name.lower(),
                      "Actual:{} ,Expected: {}".format(full_name, expected_full_name))

    @pytest.mark.positive
    @pytest.mark.parametrize("new_user_data",
                             TestDataProvider.generate_user_reg_data(only_required_fields=True,save_user=True))
    def test_registration_success_scenario_only_required_fields(self, app, new_user_data):
        # TestDataProvider.save_created_account(new_user_data["email"], new_user_data["password"])
        app.home_page.open_homepage()
        app.home_page.click_sign_in()
        app.authentication_page.create_account_section.input_email_address(new_user_data["email"])
        app.authentication_page.create_account_section.click_button_create_account()
        actual = app.authentication_page.get_page_h1_heading_text()
        pytest.assume("CREATE AN ACCOUNT" == actual, "Actual:{} ,Expected: {}".format(actual, "CREATE AN ACCOUNT"))
        actual = app.authentication_page.personal_info_section.get_section_heading()
        pytest.assume("YOUR PERSONAL INFORMATION" == actual,
                      "Actual:{} ,Expected: {}".format(actual, "YOUR PERSONAL INFORMATION"))

        app.authentication_page.personal_info_section.input_personal_info(new_user_data)
        app.authentication_page.personal_info_section.click_button_register()
        title = app.authentication_page.get_title()
        expected_title = "My account - My Store"
        pytest.assume(title == expected_title, "Actual:{} ,Expected: {}".format(title, expected_title))
        full_name = app.myaccount_page.get_logged_in_full_name()
        expected_full_name = new_user_data["first_name"] + " " + new_user_data["last_name"]
        pytest.assume(full_name == expected_full_name.lower(),
                      "Actual:{} ,Expected: {}".format(full_name, expected_full_name))

    @pytest.mark.negative
    @pytest.mark.parametrize("new_user_data,errors",
                             TestDataProvider.get_user_reg_data_list_with_errors())
    def test_registration_personal_info_page_all_negative_scenarios_without_required_field(self, app, new_user_data,
                                                                                           errors):
        app.home_page.open_homepage()
        app.home_page.click_sign_in()
        app.authentication_page.create_account_section.input_email_address(
            new_user_data["email_for_create_account_page"])
        app.authentication_page.create_account_section.click_button_create_account()
        app.authentication_page.personal_info_section.input_personal_info(new_user_data)
        app.authentication_page.personal_info_section.click_button_register(wait_for_next_page_load=False)
        actual_errors = app.authentication_page.personal_info_section.get_error_list()
        pytest.assume(len(actual_errors) == len(errors),
                      "Actual:{} ,Expected: {}".format(len(actual_errors), len(errors)))
        for i in range(len(errors)):
            pytest.assume(actual_errors[i] == errors[i], "Actual:{} ,Expected: {}".format(actual_errors[i], errors[i]))
<file_sep>/README.md
# py-test-auto-framework

Sample Test Automation project to show automation by using Python, Pytest and Selenium in Page Object Model structure. 

## Prerequisite

* Python 3.7 +
* pipenv should be installed (follow instruction here https://github.com/pypa/pipenv)


## Installation
```bash
> git clone https://github.com/abkabhishek/py-test-auto-framework.git
> cd py-test-auto-framework
> pipenv shell
> pipenv install
> export PYTHONPATH=$(pwd):$PYTHONPATH
```

## To Run Test

```python
#to run all test
pytest -v
#to run test function containing keyword (registration
pytest -v -k registration
#to run test function marked with mentioned marker (positive)
pytest -v -m positive
#to run all test and generate html report
pytest --html=report.html -v

```

* Root directory contains docker-compose file to run selenium hub and node. Running it and changing value of "environment" to "remote" in tests> config_test.json.
* Complete site's Pom and Tests should be placed inside site name folder - AutomationPractice > Module name - registration_and_login > then pom, tests, testdata.
* testdata folder contains the Test Data Provider class and maintaining created account details as well.
<file_sep>/core/com.py
"""
This is module to contain commonly used functionality like find elements
"""
import time
from sys import stdout as console

from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

WAIT_TIME_OUT = 180

class Com:

    driver = None
    wait = None
    windowTabs = {}

    def __init__(self, driver):
        Com.driver = driver
        Com.wait = Wait(driver)

    @classmethod
    def is_exist(cls, locatr):
        return cls.driver.find_elements(*Locatr.get_locatr_by(locatr))

    @classmethod
    def get_element_text_else_false(cls, elem):
        if elem:
            return elem.text
        else:
            return False

    @classmethod
    def findElement(cls, locatr, elem=None):
        """
        locatr param should be of "css|string" style
        elem param is optional selenium element, if provided then find_element will be done on that passed element
        """
        try:
            if elem:
                return elem.find_element(*Locatr.get_locatr_by(locatr))
            else:
                return cls.driver.find_element(*Locatr.get_locatr_by(locatr))
        except NoSuchElementException as e:
            print(e)
            print("Unable to find the element by: {}, locator: {}".format(*Locatr.get_locatr_by(locatr)))
            raise Exception("Element not found")

    @classmethod
    def findElements(cls, locatr, elem=None):
        """
        locatr param should be of "css|string" style
        elem param is optional selenium element, if provided then find_element will be done on that passed element
        """
        if elem:
            return elem.find_elements(*Locatr.get_locatr_by(locatr))
        else:
            return cls.driver.find_elements(*Locatr.get_locatr_by(locatr))

    @classmethod
    def element(cls, locatr):
        """
        This is the custom element function, in every pom class, every locator is created of this type function.
        User can perform action direction on the element, no need to find element first.
        Example:

        Home.Search_box().send_keys("<PASSWORD>")

        It can get multiple optional parameters at the time of actions:

        Home.Results(True,1).click()
             => first param = find_all=True - To find list of elements
             => second param = element index to return, else it will return all list.

        """

        def find_element(find_all=False, return_item=False):
            try:
                if find_all:
                    elems = cls.findElements(locatr)
                else:
                    elem = cls.findElement(locatr)

                if find_all and return_item == False and elems:
                    return elems
                elif find_all and return_item != False and elems:
                    return elems[return_item - 1]
                else:
                    return elem
            except Exception as ex:
                #                 console.write(str(ex))
                console.write("---- Element not found, Exception occurred while finding the element ----")
                print(ex)
                raise Exception("Element Not found")
                # return False

        return find_element

    @classmethod
    def elements(cls, locatr):
        """
        This is similar like element function above but its for list of elements specifically

        """

        def find_elements(return_item=False):
            try:
                elems = cls.findElements(locatr)

                if return_item == False and elems:
                    return elems
                elif return_item != False and elems:
                    return elems[return_item - 1]
                else:
                    return elems
            except Exception as ex:
                # console.write(str(ex))
                console.write("---- Element not found, Exception occurred while finding the elements ----")
                console.write(ex)
                raise Exception("Elements Not found")

        return find_elements



class Locatr:
    """
    Helper class to convert "css|string" type locator to (CSS_SELECTOR,"string")
    """

    @staticmethod
    def get_locatr_by(locatr):
        if "|" in locatr:
            locatrBy, locatrStr = locatr.split("|")

            if locatrBy.lower() == "xpath":
                return By.XPATH, locatrStr
            elif locatrBy.lower() == "id":
                return By.ID, locatrStr
            elif locatrBy.lower() == "css":
                return By.CSS_SELECTOR, locatrStr
            elif locatrBy.lower() == "name":
                return By.NAME, locatrStr
            elif locatrBy.lower() == "class":
                return By.CLASS_NAME, locatrStr
            elif locatrBy.lower() == "tagname":
                return By.TAG_NAME, locatrStr
            else:
                return By.ID, locatrStr
        else:
            raise Exception("Invalid locatr string : {}".format(locatr))


class Wait:

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

    def wait_for_element_visible(self, locatr, timeout=WAIT_TIME_OUT):
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located(Locatr.get_locatr_by(locatr))
            )
            return element
        except Exception as e:
            print(e)
            raise Exception("Element ( by: {}, locator: {}) is not visible after waiting until timeout {}".format(*Locatr.get_locatr_by(locatr),timeout))

    def wait_for_element_with_text_present(self,locatr,text,timeout=WAIT_TIME_OUT):
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.text_to_be_present_in_element(Locatr.get_locatr_by(locatr),text)
            )
            return element
        except Exception as e:
            print(e)
            raise Exception("Element ( by: {}, locator: {}) is not present with text {} after waiting until timeout {}".format(*Locatr.get_locatr_by(locatr),text,timeout))


    def is_element_present(self, locatr):
        try:
            self.driver.find_element(*Locatr.get_locatr_by(locatr))
            return True
        except Exception:
            return False

    def is_element_text_visible(self,locatr,text):
        try:
            element = self.driver.find_element(*Locatr.get_locatr_by(locatr))
            return element.is_displayed() and text in element.text
        except Exception:
            return False<file_sep>/AutomationPractice/registration_and_login/pom/page_myaccount.py
from AutomationPractice.registration_and_login.pom.base import BasePage
from AutomationPractice.registration_and_login.pom.locators import Locators


class MyaccountPage(BasePage):
    """ My Account Page Class """

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

        # Below is creating class attribute for each locator in Locator class as one Element object and one locator_* string
        for k, v in Locators.Myaccount.items():
            setattr(self, k, self.com.element(v))
            setattr(self, "elem_ " + k, v)

    def get_logged_in_full_name(self):
        return self.link_account().text.lower()
<file_sep>/AutomationPractice/registration_and_login/tests/test_login.py
import pytest
from AutomationPractice.registration_and_login.testdata.test_data_provider import TestDataProvider


class TestLogin:

    @pytest.mark.positive
    def test_open_homepage(self,app):
        app.home_page.open_homepage()
        assert("My Store" == app.home_page.get_title())


    @pytest.mark.positive
    @pytest.mark.parametrize("user_creds,page_title",
                             [({"username": "<EMAIL>", "password": "<PASSWORD>"},
                               "My account - My Store")])
    def test_login_success(self, app, user_creds, page_title):
        app.home_page.open_homepage()
        app.home_page.click_sign_in()
        app.authentication_page.login_section.perform_login(user_creds["username"], user_creds["password"])
        assert (page_title == app.authentication_page.get_title())




    @pytest.mark.negative
    @pytest.mark.parametrize("user_creds,page_title,error_count,expected_errors",
                             TestDataProvider.get_creds_list_neg_combo1())
    def test_login_failure_invalid_creds(self, app, user_creds, page_title, error_count, expected_errors):
        app.home_page.open_homepage()
        app.home_page.click_sign_in()
        app.authentication_page.login_section.perform_login(user_creds["username"], user_creds["password"],
                                                            wait_for_next_page_load=False)
        errors = app.authentication_page.login_section.get_error_list()
        pytest.assume(error_count == len(errors))
        for i in range(error_count):
            pytest.assume(expected_errors[i] == errors[i])
        pytest.assume(page_title == app.authentication_page.get_title())
<file_sep>/AutomationPractice/registration_and_login/pom/page_home.py
from AutomationPractice.registration_and_login.pom.base import BasePage
from AutomationPractice.registration_and_login.pom.locators import Locators


class HomePage(BasePage):
    """ Home Page Class """

    def __init__(self, driver, base_url=None):
        BasePage.__init__(self, driver)
        self.base_url = base_url

        # Below is creating class attribute for each locator in Locator class as one Element object and one locator_* string
        for k, v in Locators.Home.items():
            setattr(self, k, self.com.element(v))
            setattr(self, "elem_ " + k, v)

    def open_homepage(self):
        self.driver.get(self.base_url)
        self.wait_for_page_load("homepage")

    def click_sign_in(self):
        self.link_sign_in().click()
        self.wait_for_page_load("loginpage")

    def click_sign_out(self):
        self.link_sign_out().click()
<file_sep>/AutomationPractice/registration_and_login/testdata/test_data_provider.py
from faker import Faker
import os
from pprint import pprint
from sys import stdout as console

dir_path = os.path.dirname(os.path.realpath(__file__))


class TestDataProvider:
    """This is Test Data Provider class to supply test data after generating it as per requirement to test functions and saving created account in a csv file for later use."""
    email_template = "<EMAIL>"
    currentCount = None




    @classmethod
    def save_created_account(cls, email, password):
        """
        To Save created account details for later use and not to generate same email account for new registration.
        New created account should be saved through this
        """
        with open(os.path.join(dir_path, "created_accounts.csv"), "a+") as fl:
            fl.write("{}, {}\n".format(email, password))
        console.write("====== Created User is Saved =======")

    @classmethod
    def get_created_account(cls, get_all=False):
        """ To get account credentials for existing created account """
        try:
            with open(os.path.join(dir_path, "created_accounts.csv"), "r") as fl:
                if get_all:
                    account = [[account.rstrip("\n").split(", ")] for account in fl.readlines()]
                else:
                    account = fl.readline().rstrip("\n").split(", ")
        except FileNotFoundError as e:
            return 0, "No account is available"
        return account

    @classmethod
    def generate_user_reg_data(cls, count=1, without_fields=None, only_required_fields=False,save_user=False):
        """
        To Generate Personal Information Fields data for new account registration
        """
        faker = Faker()
        user_reg_data_list = []

        for i in range(count):
            user_reg_data = {}

            user_reg_data["first_name"], user_reg_data["last_name"] = faker.first_name(), faker.last_name()
            user_reg_data["email"] = cls.generate_email()
            user_reg_data["password"] = "<PASSWORD>"
            if save_user:
                cls.save_created_account(user_reg_data["email"],user_reg_data["password"])
            address = faker.address()
            first_address, second_address = address.split("\n")
            # _,state,zipcode = second_address.split()
            user_reg_data["address1"] = first_address

            user_reg_data["city"] = faker.city()
            user_reg_data["state_index"] = faker.random_int(1, 53)
            user_reg_data["zipcode"] = faker.zipcode()

            user_reg_data["mobile_phone"] = 1111111112
            user_reg_data["address_alias"] = str(user_reg_data["state_index"]) + str(user_reg_data["zipcode"])

            if only_required_fields == False:
                title = faker.boolean()
                if title:
                    user_reg_data["title"] = "mrs"
                else:
                    user_reg_data["title"] = "mr"
                dob = str(faker.date_of_birth())
                dob_year, dob_month, dob_date = dob.split("-")
                user_reg_data["dob_year"], user_reg_data["dob_month"], user_reg_data["dob_date"] = int(dob_year), int(
                    dob_month), int(dob_date)
                user_reg_data["company"] = faker.company()
                user_reg_data["address2"] = second_address
                user_reg_data["home_phone"] = 1111111111
                user_reg_data["additional_info"] = faker.text()

            if without_fields:
                for item in without_fields:
                    del user_reg_data[item]
            user_reg_data_list.append(user_reg_data)

        return user_reg_data_list

    @classmethod
    def generate_email(cls):
        """To Generated new Email for new account creation as per saved account details """
        return cls.email_template.format(cls.get_number_of_accounts() + 1)

    @classmethod
    def get_number_of_accounts(cls):
        accounts = cls.get_created_account(get_all=True)
        total_accounts = len(accounts)
        TestDataProvider.currentCount = total_accounts
        return total_accounts


    @classmethod
    def get_creds_list_neg_combo1(cls):
        """
        For Login Tests,
        It provide negative test data with expected error.
        """
        user_creds_list = [({"username": "<EMAIL>", "password": "<PASSWORD>"},
                            "Login - My Store",
                            1, ["Authentication failed."]),
                           ({"username": "<EMAIL>", "password": "<PASSWORD>"},
                            "Login - My Store",
                            1, ["Authentication failed."]),
                           ({"username": "<EMAIL>", "password": "<PASSWORD>"},
                            "Login - My Store",
                            1, ["Authentication failed."]),
                           ({"username": "", "password": ""},
                            "Login - My Store",
                            1, ["An email address required."]),
                           ({"username": "<EMAIL>", "password": ""},
                            "Login - My Store",
                            1, ["Password is required."]),
                           ({"username": "", "password": "<PASSWORD>"},
                            "Login - My Store",
                            1, ["An email address required."])
                           ]
        return user_creds_list

    @classmethod
    def get_user_reg_data_list_with_errors(cls):
        """
        For Registration Tests.
        This test function provides negative test data as required field.
        One row of data is missing with one required field at a time and their expected error.
        """
        required_fields_errors = {
            "first_name": "firstname is required.",
            "last_name": "lastname is required.",
            "email": "email is required.",
            "password": "<PASSWORD>.",
            "address1": "address1 is required.",
            "city": "city is required.",
            "state_index": "This country requires you to choose a State.",
            "zipcode": "The Zip/Postal code you've entered is invalid. It must follow this format: 00000",
            "mobile_phone": "You must register at least one phone number.",
            "address_alias": "alias is required."
        }

        generated_data = []
        for k, v in required_fields_errors.items():
            data1 = (cls.generate_user_reg_data(without_fields=[k], only_required_fields=True)[0],
                     [v])
            data1[0]["email_for_create_account_page"] = cls.generate_email()

            generated_data.append(data1)
        return generated_data
<file_sep>/AutomationPractice/registration_and_login/tests/conftest.py
"""
Shared Fixtures
"""

import json
import os
import pytest
import selenium.webdriver

from AutomationPractice.registration_and_login.pom.page_home import HomePage
from AutomationPractice.registration_and_login.pom.page_authentication import AuthenticationPage
from AutomationPractice.registration_and_login.pom.page_myaccount import MyaccountPage
from core.browser import Browser

dir_path = os.path.dirname(os.path.realpath(__file__))


@pytest.fixture
def config(scope='session'):
    # Read the file
    with open(os.path.join(dir_path, 'config_test.json')) as config_file:
        config = json.load(config_file)

    # Assert values are acceptable
    assert config['browser'] in ['firefox', 'chrome', 'Headless Chrome']
    assert isinstance(config['implicit_wait'], int)
    assert config['implicit_wait'] > 0

    # Return config so it can be used
    return config


@pytest.fixture
def app(config):
    # get Web Driver
    b = Browser.get_driver({"browser": config['browser'], "environment": config['environment'],"headless":config["headless"]})

    # Make its calls wait for elements to appear
    if config['environment']=="remote":
        b.implicitly_wait(config['implicit_wait']+30)
    else:
        b.implicitly_wait(config['implicit_wait'])

    app = App(b, config['base_url'])

    yield app

    b.quit()
    del app


class App:

    def __init__(self, driver, base_url):
        self.home_page = HomePage(driver, base_url)
        self.authentication_page = AuthenticationPage(driver)
        self.myaccount_page = MyaccountPage(driver)
