Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added app/__init__.py
Empty file.
12 changes: 12 additions & 0 deletions app/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pages.bestsellers_page import BestsellersPage
from pages.main_page import MainPage
from pages.search_results_page import SearchResultsPage


class Application:

def __init__(self, driver):
self.driver = driver
self.bestsellers_page = BestsellersPage(self.driver)
self.main_page = MainPage(self.driver)
self.search_results_page = SearchResultsPage(self.driver)
38 changes: 38 additions & 0 deletions css_selectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome(executable_path='/Users/svetlanalevinsohn/JobEasy/12-python-selenium-automation/chromedriver')

# By tag & ID
driver.find_element(By.CSS_SELECTOR, "input#twotabsearchtextbox")
# By ID
driver.find_element(By.CSS_SELECTOR, "#twotabsearchtextbox")
driver.find_element(By.ID, "twotabsearchtextbox")

# By class
driver.find_element(By.CSS_SELECTOR, ".icp-nav-flag-us")
# By multiple classes
driver.find_element(By.CSS_SELECTOR, ".icp-nav-flag-us.icp-nav-flag")
# By class + tag
driver.find_element(By.CSS_SELECTOR, "span.icp-nav-flag-us.icp-nav-flag")

# By attribute:
driver.find_element(By.CSS_SELECTOR, "input[name='email']")
driver.find_element(By.CSS_SELECTOR, "[name='email']")
driver.find_element(By.CSS_SELECTOR, "[href='/gp/help/customer/display.html/ref=ap_signin_notification_condition_of_use?ie=UTF8&nodeId=508088']")
# By multiple attributes:
driver.find_element(By.CSS_SELECTOR, "input[name='email'][type='email'][maxlength='128']")
# By attribute + class
driver.find_element(By.CSS_SELECTOR, "input.a-button-input[type='submit']")
driver.find_element(By.CSS_SELECTOR, "input.a-button-input.class[type='submit'][]")
driver.find_element(By.CSS_SELECTOR, ".a-button-input.class[type='submit'][]")
# By partial attribute
driver.find_element(By.CSS_SELECTOR, "a[href*='ap_signin_notification_condition_of_use']")
# For classes, to get partial match:
driver.find_element(By.CSS_SELECTOR, "a[class*='button']")

# From parent => child
driver.find_element(By.CSS_SELECTOR, "div#legalTextRow a[href*='condition']")

# Xpath backwards (from child to parent)
driver.find_element(By.XPATH, "//*[./a[contains(@href, 'signin_notification_condition_of_use')]]")
7 changes: 6 additions & 1 deletion features/environment.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait

from app.application import Application


def browser_init(context):
"""
:param context: Behave context
"""
context.driver = webdriver.Chrome()
context.driver = webdriver.Chrome(executable_path='/Users/svetlanalevinsohn/JobEasy/12-python-selenium-automation/chromedriver')
# context.browser = webdriver.Safari()
# context.browser = webdriver.Firefox()

context.driver.maximize_window()
context.driver.implicitly_wait(4)
context.driver.wait = WebDriverWait(context.driver, 10)
context.app = Application(context.driver)


def before_scenario(context, scenario):
Expand Down
40 changes: 40 additions & 0 deletions features/steps/amazon_main_page_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from selenium.webdriver.common.by import By
from behave import given, when, then
from selenium.webdriver.support import expected_conditions as EC
from time import sleep


HAM_MENU = (By.ID, 'nav-hamburger-menu')
FOOTER_LINKS = (By.CSS_SELECTOR, '.navFooterDescItem a')
SIGN_IN = (By.CSS_SELECTOR, "#nav-signin-tooltip .nav-action-button")


@given('Open amazon page')
def open_amazon(context):
context.app.main_page.open_main()


@when('Search for {product}')
def search_product(context, product):
context.app.main_page.search_product(product)


@when('Click on button from SignIn popup')
def click_sign_in(context):
e = context.driver.wait.until(EC.element_to_be_clickable(SIGN_IN), message='Sign in not clickable')
e.click()


@then('Verify hamburger menu is present')
def verify_ham_menu_present(context):
context.driver.find_element(*HAM_MENU)


@then('Verify that footer has {expected_link_count} links')
def verify_link_count(context, expected_link_count):
expected_link_count = int(expected_link_count)

links = context.driver.find_elements(*FOOTER_LINKS)

assert len(links) == expected_link_count, \
f'Expected {expected_link_count} links, but got {len(links)}'
11 changes: 11 additions & 0 deletions features/steps/bestsellers_page_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from behave import given, then


@given('Open Amazon Bestsellers')
def open_amazon_bestsellers(context):
context.app.bestsellers_page.open_bestsellers()


@then('User can click through top links and verify correct page opens')
def click_thru_top(context):
context.app.bestsellers_page.click_thru_top_links()
44 changes: 44 additions & 0 deletions features/steps/product_page_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from selenium.webdriver.common.by import By
from behave import when, given, then
from time import sleep


ADD_TO_CART_BTN = (By.ID, 'add-to-cart-button')
PRODUCT_NAME = (By.ID, 'productTitle')
COLOR_OPTIONS = (By.CSS_SELECTOR, "#variation_color_name li")
CURRENT_COLOR = (By.CSS_SELECTOR, "#variation_color_name .selection")


@given('Open Amazon product {product_id} page')
def open_amazon_product(context, product_id):
context.driver.get(f'https://www.amazon.com/dp/{product_id}/')


@when('Click on Add to cart button')
def click_add_to_cart(context):
context.driver.find_element(*ADD_TO_CART_BTN).click()
sleep(2)


@when('Store product name')
def get_product_name(context):
context.product_name = context.driver.find_element(*PRODUCT_NAME).text
print(f'Current product: {context.product_name}')


@then('Verify user can click through colors')
def verify_can_click_colors(context):
expected_colors = ['Black', 'Solid Black']
actual_colors = []

colors = context.driver.find_elements(*COLOR_OPTIONS)

for color in colors[:3]:
color.click()
current_color = context.driver.find_element(*CURRENT_COLOR).text
actual_colors += [current_color]

assert expected_colors == actual_colors, \
f'Expected colors {expected_colors} did not match actual {actual_colors}'


8 changes: 8 additions & 0 deletions features/steps/search_results_page_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from selenium.webdriver.common.by import By
from behave import given, when, then


@then('Search results for {expected_result} are shown')
def verify_search_results(context, expected_result):
actual_result = context.driver.find_element(By.XPATH, "//span[@class='a-color-state a-text-bold']").text
assert expected_result == actual_result, f'Error! Expected {expected_result}, but got {actual_result}'
8 changes: 8 additions & 0 deletions features/steps/sign_in_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from selenium.webdriver.common.by import By
from behave import then
from selenium.webdriver.support import expected_conditions as EC


@then('Verify Sign in page opened')
def verify_sign_in_opened(context):
context.driver.wait.until(EC.url_contains('ap/signin'), message='Signin URL did not open')
10 changes: 10 additions & 0 deletions features/tests/amazon_main.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Created by svetlanalevinsohn at 10/1/22
Feature: Tests for Amazon main page

Scenario: Hamburger menu is present
Given Open amazon page
Then Verify hamburger menu is present

Scenario: Footer has correct amount of links
Given Open amazon page
Then Verify that footer has 38 links
33 changes: 33 additions & 0 deletions features/tests/amazon_search.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Created by svetlanalevinsohn at 9/24/22
Feature: Tests for amazon search

Scenario: User can search for coffee
Given Open amazon page
When Search for coffee
Then Search results for "coffee" are shown
#
# Scenario: User can search for mug
# Given Open amazon page
# When Search for mug
# Then Search results for "mug" are shown

Scenario Outline: User can search for a product
Given Open amazon page
When Search for <product>
Then Search results for <search_result> are shown
Examples:
|product |search_result |
|coffee |"coffee" |
|mug |"mug" |
|dress |"dress" |
|Tritan Farm to Table Pitcher on amazon |"Tritan Farm to Table Pitcher on amazon" |

Scenario: User can add a product to the cart
Given Open Amazon page
When Search for Tritan Farm to Table Pitcher on amazon
And Click on the first product
And Store product name
And Click on Add to cart button
And Open cart page
Then Verify cart has 1 item(s)
And Verify cart has correct product
5 changes: 5 additions & 0 deletions features/tests/product_details.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Feature: Tests for product page

Scenario: User can select colors
Given Open Amazon product B07MNHBRCJ page
Then Verify user can click through colors
7 changes: 7 additions & 0 deletions features/tests/sign_in.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Created by svetlanalevinsohn at 7/16/22
Feature: Sign in test cases

Scenario: Sign In page can be opened from SignIn popup
Given Open Amazon page
When Click on button from SignIn popup
Then Verify Sign in page opened
Empty file added pages/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions pages/base_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class Page:

def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(self.driver, 15)
self.base_url = 'https://www.amazon.com/'

def open_url(self, end_url=''):
url = f'{self.base_url}{end_url}'
print(f'Opening URL: {url}')
self.driver.get(url)

def find_element(self, *locator):
return self.driver.find_element(*locator)

def find_elements(self, *locator):
return self.driver.find_elements(*locator)

def click(self, *locator):
self.driver.find_element(*locator).click()

def input_text(self, text, *locator):
e = self.driver.find_element(*locator)
e.clear()
e.send_keys(text)
print(f'Inputting text: {text}')

def wait_for_element_click(self, *locator):
e = self.wait.until(EC.element_to_be_clickable(locator))
e.click()

def wait_for_element_disappear(self, *locator):
self.wait.until(EC.invisibility_of_element(locator))

def wait_for_element_appear(self, *locator):
return self.wait.until(EC.presence_of_element_located(locator))

def verify_element_text(self, expected_text, *locator):
actual_text = self.driver.find_element(*locator).text
assert expected_text == actual_text, f'Expected {expected_text}, but got {actual_text}'

def verify_partial_text(self, expected_text, *locator):
actual_text = self.driver.find_element(*locator).text
assert expected_text in actual_text, \
f'Expected text {expected_text} is not in {actual_text}'

def verify_url_contains_query(self, query):
self.wait.until(EC.url_contains(query))
23 changes: 23 additions & 0 deletions pages/bestsellers_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from selenium.webdriver.common.by import By

from pages.base_page import Page


class BestsellersPage(Page):
TOP_LINKS = (By.CSS_SELECTOR, '#zg_header a')
HEADER = (By.CSS_SELECTOR, '#zg_banner_text')

def open_bestsellers(self):
self.open_url('gp/bestsellers/')

def click_thru_top_links(self):
top_links = self.driver.find_elements(*self.TOP_LINKS) # [WebEl1,WebEl2, WebEl3,... ]
print(top_links)

for i in range(len(top_links)): # for x from 0 to 4
link_to_click = self.driver.find_elements(*self.TOP_LINKS)[i]
link_text = link_to_click.text
link_to_click.click()
header_text = self.driver.find_element(*self.HEADER).text
assert link_text in header_text, f'Expected {link_text} to be in {header_text}'

15 changes: 15 additions & 0 deletions pages/main_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from selenium.webdriver.common.by import By
from pages.base_page import Page


class MainPage(Page):
SEARCH_INPUT = (By.ID, 'twotabsearchtextbox')
SEARCH_BTN = (By.ID, 'nav-search-submit-button')

def open_main(self):
self.open_url()

def search_product(self, product):
self.input_text(product, *self.SEARCH_INPUT)
self.click(*self.SEARCH_BTN)

10 changes: 10 additions & 0 deletions pages/search_results_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from selenium.webdriver.common.by import By

from pages.base_page import Page


class SearchResultsPage(Page):
SEARCH_RESULTS = (By.CSS_SELECTOR, '.a-color-state.a-text-bold')

def verify_search_results(self, expected_result):
self.verify_element_text(expected_result, *self.SEARCH_RESULTS)
14 changes: 10 additions & 4 deletions sample_script.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# init driver
driver = webdriver.Chrome()
driver = webdriver.Chrome(executable_path='/Users/svetlanalevinsohn/JobEasy/12-python-selenium-automation/chromedriver')
driver.maximize_window()
driver.implicitly_wait(5) # applied to find_element(s) / #100 ms if element is found
driver.wait = WebDriverWait(driver, 10)

# open the url
driver.get('https://www.google.com/')

search = driver.find_element(By.NAME, 'q')
search.clear()
search.send_keys('Dress')
search.send_keys('Car')

# wait for 4 sec
sleep(4)
# sleep(4)
btn = (By.NAME, 'btnK')
driver.wait.until(EC.element_to_be_clickable(btn), message='Search btn not clickable') # 500 ms

# click search
driver.find_element(By.NAME, 'btnK').click()

# verify
assert 'dress' in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}"
assert 'car' in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}"
print('Test Passed')

driver.quit()