Skip to content

Commit

Permalink
Merge pull request #6 from ZhikharevAl/feature/tests
Browse files Browse the repository at this point in the history
Feature/tests
  • Loading branch information
ZhikharevAl authored Nov 15, 2024
2 parents be93707 + c88940d commit ff0d2cc
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 25 deletions.
1 change: 1 addition & 0 deletions config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
REGISTER_URL = "register.htm"
OPEN_NEW_ACCOUNT_URL = "openaccount.htm"
TRANSFER_FUNDS_URL = "transfer.htm"
UPDATE_PROFILE_URL = "updateprofile.htm"
17 changes: 12 additions & 5 deletions pages/base_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import allure
from playwright.sync_api import Locator, Page, expect
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError

from config.config import BASE_URL

Expand Down Expand Up @@ -51,14 +52,21 @@ def contains_text(self, selector: str, text: str) -> bool:
else:
return True

def clear_text(self, selector: str) -> None:
"""Clear text in element."""
self.find_element(selector).clear()

def fill_text(self, selector: str, text: str) -> None:
"""Fill text in element.
Args:
selector (str): Element selector
text (str): Text to fill
"""
self.find_element(selector).fill(text)
element: Locator = self.find_element(selector)
self.page.on("dialog", lambda dialog: dialog.accept())
element.clear()
element.fill(text)

@allure.step("Click element by role {role} with name {name}")
def click_by_role(self, role: str, name: str) -> None:
Expand All @@ -73,11 +81,10 @@ def click_by_role(self, role: str, name: str) -> None:
def get_by_role_to_be_visible(self, role: str, name: str) -> bool:
"""Checks that the element is visible."""
try:
expect(self.page.get_by_role(role, name=name)) # type: ignore
except AssertionError:
element: Locator = self.page.get_by_role(role, name=name) # type: ignore
return element.is_visible()
except PlaywrightTimeoutError:
return False
else:
return True

@allure.step("Select option {value} in dropdown {selector}")
def select_option(self, selector: str, value: str) -> None:
Expand Down
5 changes: 0 additions & 5 deletions pages/main_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,3 @@ def login(self, username: str, password: str) -> None:
def is_register_button_visible(self) -> bool:
"""Checks that the register button is visible."""
return self.get_by_role_to_be_visible("link", "Register")

@property
def is_transfer_button_visible(self) -> bool:
"""Checks that the transfer funds button is visible."""
return self.get_by_role_to_be_visible("link", "Transfer Funds")
14 changes: 14 additions & 0 deletions pages/overview_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,24 @@ def is_logged_in(self) -> bool:
self.ACCOUNT_OVERVIEW_HEADER, self.ACCOUNT_OVERVIEW_HEADER_TEXT
)

@property
def is_transfer_button_visible(self) -> bool:
"""Checks that the transfer funds button is visible."""
return self.get_by_role_to_be_visible("link", "Transfer Funds")

@property
def is_update_contact_info(self) -> bool:
"""Checks that the update contact info button is visible."""
return self.get_by_role_to_be_visible("link", "Update Contact Info")

def click_open_new_account(self) -> None:
"""Click on Open new account button."""
self.click_by_role("link", "Open New Account") # type: ignore

def click_transfer_funds(self) -> None:
"""Click transfer funds button."""
self.click_by_role("link", self.TRANSFER_FUNDS_BUTTON) # type: ignore

def click_update_profile(self) -> None:
"""Click update profile button."""
self.click_by_role("link", "Update Contact Info") # type: ignore
46 changes: 46 additions & 0 deletions pages/update_profile_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import allure
from playwright.sync_api import Page

from config.config import UPDATE_PROFILE_URL
from data.user_data import UserData
from pages.base_page import BasePage


class UpdateProfilePage(BasePage):
"""The update profile page."""

def __init__(self, page: Page) -> None:
"""The update profile page."""
super().__init__(page, url=UPDATE_PROFILE_URL)

FIRST_NAME_INPUT = '[id="customer.firstName"]'
LAST_NAME_INPUT = '[id="customer.lastName"]'
STREET_INPUT = '[id="customer.address.street"]'
CITY_INPUT = '[id="customer.address.city"]'
STATE_INPUT = '[id="customer.address.state"]'
ZIP_CODE_INPUT = '[id="customer.address.zipCode"]'
PHONE_INPUT = '[id="customer.phoneNumber"]'
UPDATE_BUTTON = "Update Profile"
UPDATE_MESSAGE_LOCATOR = "#updateProfileResult"
UPDATE_MESSAGE = "Profile Updated"

@allure.step("Fill registration form")
def update_profile(self, user_data: UserData) -> None:
"""Fill all fields in registration form."""
self.page.on("dialog", lambda dialog: dialog.accept())
self.fill_text(self.FIRST_NAME_INPUT, user_data.first_name)
self.fill_text(self.LAST_NAME_INPUT, user_data.last_name)
self.fill_text(self.STREET_INPUT, user_data.street)
self.fill_text(self.CITY_INPUT, user_data.city)
self.fill_text(self.STATE_INPUT, user_data.state)
self.fill_text(self.ZIP_CODE_INPUT, user_data.zip_code)
self.fill_text(self.PHONE_INPUT, user_data.phone)

def click_update_button(self) -> None:
"""Click update button."""
self.click_by_role("button", self.UPDATE_BUTTON) # type: ignore

@property
def is_updated(self) -> bool:
"""Check if profile is updated."""
return self.contains_text(self.UPDATE_MESSAGE_LOCATOR, self.UPDATE_MESSAGE)
90 changes: 78 additions & 12 deletions tests/base/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,93 @@
from pages.overview_page import OverviewPage
from pages.register_page import RegisterPage
from pages.transfer_page import TransferPage
from pages.update_profile_page import UpdateProfilePage


class PageFactory:
"""Factory for creating pages."""

def __init__(self, page: Page) -> None:
"""Constructor."""
self.page: Page = page

def create_main_page(self) -> MainPage:
"""Create main page."""
return MainPage(self.page)

def create_overview_page(self) -> OverviewPage:
"""Create overview page."""
return OverviewPage(self.page)

def create_register_page(self) -> RegisterPage:
"""Create register page."""
return RegisterPage(self.page)

def create_open_new_account_page(self) -> OpenNewAccountPage:
"""Create open new account page."""
return OpenNewAccountPage(self.page)

def create_transfer_page(self) -> TransferPage:
"""Create transfer page."""
return TransferPage(self.page)

def create_update_profile_page(self) -> UpdateProfilePage:
"""Create update profile page."""
return UpdateProfilePage(self.page)


class BaseTest:
"""The base class for all tests."""

data: Data

main_page: MainPage
overview_page: OverviewPage
register_page: RegisterPage
open_new_account_page: OpenNewAccountPage
transfer_page: TransferPage
page: Page

@pytest.fixture(autouse=True)
def setup(cls, page: Page) -> None:
"""The setup function."""
"""Function that is called before each test."""
cls.page = page
cls.data = Data()
cls.main_page = MainPage(page)
cls.overview_page = OverviewPage(page)
cls.register_page = RegisterPage(page)
cls.open_new_account_page = OpenNewAccountPage(page)
cls.transfer_page = TransferPage(page)

factory = PageFactory(page)

# Initialize pages using the factory
cls._main_page: MainPage = factory.create_main_page()
cls._overview_page: OverviewPage = factory.create_overview_page()
cls._register_page: RegisterPage = factory.create_register_page()
cls._open_new_account_page: OpenNewAccountPage = (
factory.create_open_new_account_page()
)
cls._transfer_page: TransferPage = factory.create_transfer_page()
cls._update_profile_page: UpdateProfilePage = (
factory.create_update_profile_page()
)

@property
def main_page(self) -> MainPage:
"""Get the main page instance."""
return self._main_page

@property
def overview_page(self) -> OverviewPage:
"""Get the overview page instance."""
return self._overview_page

@property
def register_page(self) -> RegisterPage:
"""Get the register page instance."""
return self._register_page

@property
def open_new_account_page(self) -> OpenNewAccountPage:
"""Get the open new account page instance."""
return self._open_new_account_page

@property
def transfer_page(self) -> TransferPage:
"""Get the transfer page instance."""
return self._transfer_page

@property
def update_profile_page(self) -> UpdateProfilePage:
"""Get the update profile page instance."""
return self._update_profile_page
48 changes: 48 additions & 0 deletions tests/test_update_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import allure

from config.config import BASE_URL, UPDATE_PROFILE_URL
from data.user_data import UserData
from pages.main_page import MainPage
from pages.overview_page import OverviewPage
from tests.base.base_test import BaseTest


@allure.epic("Banking Application")
@allure.feature("Update Profile")
@allure.description_html("""
<h2>Testing Update Profile Functionality</h2>
<p>This test verifies the ability to update a user's profile information:</p>
<ul>
<li>Update profile information with new data</li>
<li>Confirm the profile update is completed successfully</li>
</ul>
<p>The test performs the following operations:</p>
<ul>
<li>Navigate to the Update Profile page</li>
<li>Enter the new profile information</li>
<li>Click the Update button</li>
<li>Verify the profile update is marked as complete</li>
</ul>
<p>Expected Results:</p>
<ul>
<li>User can access the Update Profile page</li>
<li>Profile information is successfully updated</li>
<li>Update completion is confirmed on the page</li>
</ul>
""")
class TestUpdateProfile(BaseTest):
"""Test update profile."""

def test_update_profile(
self,
login: tuple[MainPage, OverviewPage], # noqa: ARG002
random_user_data: UserData,
) -> None:
"""Test update profile."""
self.overview_page.click_update_profile()
assert self.update_profile_page.expect_url(
f"{BASE_URL}{UPDATE_PROFILE_URL}"
), "URL does not match expected value"
self.update_profile_page.update_profile(random_user_data) # type: ignore
self.update_profile_page.click_update_button()
assert self.update_profile_page.is_updated, "Profile is not updated"
17 changes: 14 additions & 3 deletions tests/ui/test_ui_elements.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import allure

from pages.main_page import MainPage
from pages.overview_page import OverviewPage
from tests.base.base_test import BaseTest


Expand All @@ -12,11 +14,13 @@
<li>Navigation to main page</li>
<li>Checking registration button presence</li>
<li>Checking transfer funds button presence</li>
<li>Checking update contact info button presence</li>
</ul>
<p>Expected Results:</p>
<ul>
<li>Registration button should be visible</li>
<li>Transfer funds button should be visible</li>
<li>Update contact info button should be visible</li>
</ul>
""")
class TestUIElements(BaseTest):
Expand All @@ -31,7 +35,14 @@ def test_register_button(self) -> None:

@allure.story("Transfer Funds Button Visibility")
@allure.severity(severity_level="MINOR")
def test_transfer_funds(self) -> None:
def test_transfer_funds(self, login: tuple[MainPage, OverviewPage]) -> None: # noqa: ARG002
"""The test checks that the register button is visible."""
self.main_page.navigate()
assert self.main_page.is_transfer_button_visible
self.overview_page.navigate()
assert self.overview_page.is_transfer_button_visible

@allure.story("Update Contact Info Button Visibility")
@allure.severity(severity_level="MINOR")
def test_update_contact_info(self, login: tuple[MainPage, OverviewPage]) -> None: # noqa: ARG002
"""The test checks that the update contact info button is visible."""
self.overview_page.navigate()
assert self.overview_page.is_update_contact_info

0 comments on commit ff0d2cc

Please sign in to comment.