diff --git a/HW2.py b/HW2.py new file mode 100644 index 000000000..d1ed5fd79 --- /dev/null +++ b/HW2.py @@ -0,0 +1,31 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.service import Service +from webdriver_manager.chrome import ChromeDriverManager +from time import sleep + +from selenium import webdriver +from selenium.webdriver.common.by import By +import time + + + +driver_path = ChromeDriverManager().install() + +# init driver +driver = webdriver.Edge() + +driver.get("https://www.target.com/") + +driver.find_element(By.XPATH, "//span[@class='styles__LinkText-sc-1e1g60c-3 dZfgoT h-margin-r-x3']").click() + +driver.find_element(By.XPATH, "//a[@data-test='accountNav-signIn' and @href='/account']").click() + +sleep(4) + +driver.find_element(By.ID, 'login').text +expected_result = 'Sign into your Target account' +actual_result = driver.find_element(By.XPATH, "//h1[@class='styles__StyledHeading-sc-1xmf98v-0 styles__AuthHeading-sc-kz6dq2-2 jhKFiw kcHdEa']").text +assert expected_result == actual_result, f'Expected "{expected_result}" but got "{actual_result}"' + +print("Test Passed") \ No newline at end of file diff --git a/Locators for Google.py b/Locators for Google.py new file mode 100644 index 000000000..d4382c7cf --- /dev/null +++ b/Locators for Google.py @@ -0,0 +1,28 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By + +# init driver +driver = webdriver.Chrome() + +# By ID +driver.find_element(By.ID, 'twotabsearchtextbox') + +# By Xpath +driver.find_element(By.XPATH, "//a[@href='/ref=nav_logo']") +driver.find_element(By.XPATH, "//input[@aria-label='Search']") +driver.find_element(By.XPATH, "//input[@name='field-keywords']") + +# By Xpath, multiple attributes +driver.find_element(By.XPATH, "//input[@tabindex='0' and @aria-label='Search']") +driver.find_element(By.XPATH, "//input[@tabindex='0' and @aria-label='Search' and @another_attribute....]") + +# By Xpath, text +driver.find_element(By.XPATH, "//h2[text()='Deals on overstock items']") +driver.find_element(By.XPATH, "//a[text()='Best Sellers' and @data-csa-c-content-id='nav_cs_bestsellers']") + +# By Xpath, partial attribute +driver.find_element(By.XPATH, "//a[contains(@href, 'nav_cs_bestsellers')]") +driver.find_element(By.XPATH, "//span[contains(text(), 'BELLA 21 Piece Cook Bake')]") # by partial text + +# By Xpath, multiple nodes +driver.find_element(By.XPATH, "//div[@id='nav-xshop-container']//a[contains(@href, 'bestsellers')]") diff --git a/amazon_search.py b/amazon_search.py new file mode 100644 index 000000000..c5c2b5301 --- /dev/null +++ b/amazon_search.py @@ -0,0 +1,19 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then + + +@given('Open Amazon page') +def open_amazon(context): + context.driver.get('https://www.amazon.com/') + + +@when('Search for {search_word} on amazon') +def search_product(context, search_word): + context.driver.find_element(By.ID, 'twotabsearchtextbox').send_keys(search_word) + context.driver.find_element(By.ID, 'nav-search-submit-button').click() + + +@then('User sees results for {expected_result}') +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'Expected {expected_result} but got {actual_result}' \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/application.py b/app/application.py new file mode 100644 index 000000000..5675d0625 --- /dev/null +++ b/app/application.py @@ -0,0 +1,18 @@ +from pages.base_page import Page +from pages.bestsellers_page import BestsellersPage +from pages.main_page import MainPage +from pages.search_results_page import SearchResultsPage +from pages.target_help_page import TargetHelpPage +from pages.target_sign_in import TargetSignIn + + +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) + self.base_page = Page(self.driver) + self.target_help_page = TargetHelpPage(self.driver) + self.target_sign_in = TargetSignIn(self.driver) diff --git a/css_selectos.py b/css_selectos.py new file mode 100644 index 000000000..57854dcf7 --- /dev/null +++ b/css_selectos.py @@ -0,0 +1,34 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By + +# init driver +driver = webdriver.Chrome() + +# By ID +driver.find_element(By.ID, 'twotabsearchtextbox') + +# By CSS, ID +driver.find_element(By.CSS_SELECTOR, '#twotabsearchtextbox') +driver.find_element(By.CSS_SELECTOR, 'input#twotabsearchtextbox') + +# By CSS, class(es) +driver.find_element(By.CSS_SELECTOR, 'span.icp-nav-flag-us') +driver.find_element(By.CSS_SELECTOR, 'span.icp-nav-flag.icp-nav-flag-us') +# by class, without a tag +driver.find_element(By.CSS_SELECTOR, '.icp-nav-flag') + +# By CSS, attributes +driver.find_element(By.CSS_SELECTOR, "a[href='/gp/help/customer/display.html/ref=ap_signin_notification_condition_of_use?ie=UTF8&nodeId=508088']") +# partial match +driver.find_element(By.CSS_SELECTOR, "a[href*='ap_signin_notification_condition_of_use']") +driver.find_element(By.CSS_SELECTOR, "input[type='email'][name='email'][maxlength='128']") +# mix of ids, classes, attributes: +driver.find_element(By.CSS_SELECTOR, "input#ap_email[type='email']") +driver.find_element(By.CSS_SELECTOR, "input#ap_email.auth-autofocus.a-input-text[type='email']") + +# by multiple nodes +driver.find_element(By.CSS_SELECTOR, "ul.hmenu-visible li a[href*='new-releases']") + + +driver.find_element(By.XPATH, "//div[@class='nav-search-facade' and .//span[@id='nav-search-label-id']]") + diff --git a/features/environment.py b/features/environment.py index 0930bc703..d9d7ce9b8 100755 --- a/features/environment.py +++ b/features/environment.py @@ -1,34 +1,96 @@ +import allure +from allure_commons.types import AttachmentType +from app.application import Application + from selenium import webdriver +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support.events import EventFiringWebDriver from selenium.webdriver.chrome.service import Service -from webdriver_manager.chrome import ChromeDriverManager + +from support.logger import logger, MyListener + +# Allure command: +# behave -f allure_behave.formatter:AllureFormatter -o test_results/ features/tests/product_page.feature -def browser_init(context): +def browser_init(context, my_test_name): """ :param context: Behave context + :param my_test_name: scenario.name """ - driver_path = ChromeDriverManager().install() - service = Service(driver_path) - context.driver = webdriver.Chrome(service=service) + # service = Service('/Users/svetlanalevinsohn/JobEasy/13-python-selenium-automation/chromedriver') + # service = Service('/Users/svetlanalevinsohn/JobEasy/12-python-selenium-automation/geckodriver') + # context.driver = webdriver.Chrome(service=service) + # context.driver = webdriver.Firefox(service=service) + # context.driver = webdriver.Safari() - context.driver.maximize_window() + ## HEADLESS MODE #### + # options = webdriver.ChromeOptions() + # options.add_argument('--headless') + # context.driver = webdriver.Chrome( + # chrome_options=options, + # service=service + # ) + + ### EventFiringWebDriver - log file ### + ### for drivers ### + # context.driver = EventFiringWebDriver( + # webdriver.Chrome(service=service), + # MyListener() + # ) + # for headless mode ### + # context.driver = EventFiringWebDriver(webdriver.Chrome(chrome_options = options), MyListener()) + + # for browerstack ### + # Register for BrowserStack, then grab it from https://www.browserstack.com/accounts/settings + bs_user = 'matthieugeorgesj_JtmSUb' + bs_key = 'uwqnNujyqfKizxyATGws' + + desired_cap = { + 'browser': 'Safari', + 'os': 'OS X', + 'os_Version': 'Big Sur', + 'name': 'test_name' + } + + from selenium.webdriver.chrome.options import Options as ChromeOptions + options = ChromeOptions() + options.browser_version = '92' + options.platform_name = 'Windows 11' + cloud_options = {} + cloud_options['build'] = 'my_test_build' + cloud_options['name'] = my_test_name + options.set_capability('cloud:options', cloud_options) + + + url = f'http://{bs_user}:{bs_key}@hub-cloud.browserstack.com/wd/hub' + context.driver = webdriver.Remote(url, options=options) context.driver.maximize_window() - context.driver.implicitly_wait(4) + context.driver.implicitly_wait(5) + context.driver.wait = WebDriverWait(context.driver, 10) + + context.app = Application(context.driver) def before_scenario(context, scenario): print('\nStarted scenario: ', scenario.name) - browser_init(context) + logger.info(f'Started scenario: {scenario.name}') + browser_init(context, scenario.name) def before_step(context, step): print('\nStarted step: ', step) + logger.info(f'Started step: {step}') def after_step(context, step): if step.status == 'failed': + logger.error(f'Step failed: {step}') print('\nStep failed: ', step) + # Mark test case as FAILED on BrowserStack: + # context.driver.execute_script( + # 'browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "Step failed"}}') def after_scenario(context, feature): diff --git a/features/steps/Algorithms.py b/features/steps/Algorithms.py new file mode 100644 index 000000000..ec4663280 --- /dev/null +++ b/features/steps/Algorithms.py @@ -0,0 +1,108 @@ +# algo 1!!!! +# def sumofdigits(n): +# result = 0 +# num = n % 10 +# result = result + num +# n = n // 10 +# num = n % 10 +# result = result + num +# n = n // 10 +# result = result + n +# +# +# +# print(result) +# +# +# sumofdigits(521) +# +# def maxnum(n): +# result = [124, 21, 32] +# result = max(result) +# print(result) +# +# maxnum(1) +# +# algo 2!!!! +# def split(n): +# if len(n) % 2 == 0: +# split = int(len(n) / 2) +# c = int(split) +# h1 = (n[c:]) +# h2 = (n[:c]) +# h3 = ''.join([h1, h2]) +# print(h3) +# else: +# split = int(len(n) / 2) +# c = int(split + 1) +# h1 = (n[c:]) +# # h2 = (n[:c]) +# h4 = ''.join([h1, h2]) +# +# print(split) +# print(h1) +# print(h2) +# print(h3) +# print(h4) +# +# +# split('oda') #ado +# +# def unique(n): +# seen = set() +# uniq = [] +# for x in n: +# uniq.append(x) +# seen.add(x) +# u = len(uniq) +# s = len(seen) +# if u == s: +# print("True") +# else: print("False") +# +# +# unique('fuisr') +# +# +# algo 3!!!! +# def arithmetica(num_list): +# mean = sum(num_list)/len(num_list) +# num_list = [i for i in num_list if i <= mean] +# return num_list +# +# +# cat = [1, 3, 5, 6, 4, 10, 2, 3] +# print(arithmetica(cat)) +# +# +# def low(n): +# n.sort() +# return n[0:2] +# +# +# kat = [198, 3, 4, 9, 10, 9, 2] +# print(low(kat)) + + +#algo 4!!!! +# def even_1st(list): +# list = (sorted(list, key=lambda x: [x % 2, x])) +# print(list) +# +# +# o = [7, 9, 3, 5, 6, 4, 10, 3, 2] +# even_1st(o) + + +def Increment(num): + str(num) + for i in num: + d = 0 + i + print(d) + + +f = [1, 8, 9] +Increment(f) + +h = ["a", "b", "c"] + diff --git a/features/steps/Extras HW.py b/features/steps/Extras HW.py new file mode 100644 index 000000000..4317bb6de --- /dev/null +++ b/features/steps/Extras HW.py @@ -0,0 +1,32 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep +from pages.base_page import Page +from selenium.webdriver.support import expected_conditions as EC + +product_info = (By.CSS_SELECTOR, 'a[data-test="product-title"]') +bestsellers = (By.CSS_SELECTOR, '#zg_header a') +banner = (By.CSS_SELECTOR, 'span#zg_banner_text') + + +@then('Verify product names and images displays') +def verify_product(context): + context.driver.wait.until(EC.presence_of_all_elements_located(product_info)) + + +@when('Click headers') +def click_headers(context): + sleep(10) + top_links = context.driver.find_elements(*bestsellers) + print(top_links) + + for i in range(len(top_links)): # for x from 0 to 4 + link_to_click = context.driver.find_elements(*bestsellers)[i] + link_text = link_to_click.text + link_to_click.click() + header_text = context.driver.find_element(*banner).text + assert link_text in header_text, f'Expected {link_text} to be in {header_text}' + + + + diff --git a/features/steps/HW3.py b/features/steps/HW3.py new file mode 100644 index 000000000..735b17b81 --- /dev/null +++ b/features/steps/HW3.py @@ -0,0 +1,44 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.service import Service +from webdriver_manager.chrome import ChromeDriverManager +from time import sleep +from behave import given, when, then + +driver_path = ChromeDriverManager().install() + +# init driver +driver = webdriver.Chrome() + + +@given("Open Target page") +def target_page(context): + context.driver.get('https://www.target.com/') + context.driver.get('https://www.target.com/') + sleep(1) + +@when("Click on cart icon") +def sign_in(context): + context.driver.find_element(By.CSS_SELECTOR, "a[aria-label='cart 0 items']").click() + sleep(4) + +@then("Verify cart page is present") +def verify_sign(context): + context.driver.find_element(By.CSS_SELECTOR, "h1.styles__StyledHeading-sc-1xmf98v-0").is_displayed() + print('TEST 1 PASSED') + +@when("Click on sign in icon") +def sign_out(context): + sleep(2) + context.driver.find_element(By.CSS_SELECTOR, "a[aria-expanded='false'][aria-label='Account, sign in']").click() + sleep(1) + +@when("Click on sign in button") +def sign_in_button(context): + context.driver.find_element(By.CSS_SELECTOR, "a[data-test='accountNav-signIn']").click() + sleep(4) + +@then("Verify sign in page is present") +def verify_sign(context): + context.driver.find_element(By.CSS_SELECTOR, "h1.styles__StyledHeading-sc-1xmf98v-0").is_displayed() + print('TEST 2 PASSED') diff --git a/features/steps/HW4.py b/features/steps/HW4.py new file mode 100644 index 000000000..1f035490e --- /dev/null +++ b/features/steps/HW4.py @@ -0,0 +1,70 @@ +from selenium.webdriver import Keys +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + +#HOMEWORK 4.1 +searched_product = (By.CSS_SELECTOR, "span.h-text-bs.h-display-flex.h-flex-align-center.h-text-grayDark.h-margin-l-x2") +search_box = (By.ID, 'search') +search_button = (By.CSS_SELECTOR, "button.styles__SearchButton-sc-wnzihy-3.SOItS") + +@given('Open Target site') +def open_target_page(context): + context.driver.get('https://www.target.com/') + +@when('Input {product} into search bar') +def input_product(context, product): + context.driver.find_element(*search_box).send_keys(product) + context.driver.find_element(*search_button).click() + sleep(2) + +@then('Item results for {product} are displayed') +def product_results(context, product): + assert (context.driver.find_element(*searched_product).text == product) + print('TEST PASSED') + + +#HOMEWORK 4.2 +benefit_cells = (By.CSS_SELECTOR, "div.cell-item-content") + +@given('Open Target benefit page') +def open_page(context): + context.driver.get('https://www.target.com/circle') + sleep(2) + +@then("10 Benefit cells populate") +def benefit_populate(context): + benefit_amount = context.driver.find_elements(*benefit_cells) + assert 10 == len(benefit_amount) + print('EXACTLY TEN') + + +#HOMEWORK 4.3 +add_cart = (By.XPATH, "//button[text()='Add to cart']") +add_cart2 = (By.XPATH, "//button[text()='Add to cart' and @data-test='orderPickupButton']") +zip_code = (By.CSS_SELECTOR, ".styles__ButtonPrimary-sc-5fh6rr-0.hCWYcY.bEdlr") +pick_pickup = (By.ID, "addToCartButtonOrTextIdFor14721821") +cart_button = (By.CSS_SELECTOR, "a[href='/cart?prehydrateClick=true']") +cart_filled = (By.CSS_SELECTOR, "div.h-padding-v-default") +go_cart = (By.XPATH, "//button[text()='Continue shopping']") + +@when('Add any item to cart') +def add_item(context): + sleep(4) + context.driver.find_element(*add_cart).click() + context.driver.find_element(*add_cart2).click() + + +@when("Go to cart") +def go_cart(context): + sleep(2) + context.driver.get('https://www.target.com/') + context.driver.find_element(*cart_button).click() + sleep(2) + +@then('Verify an item is in cart') +def filled_cart(context): + context.driver.find_element(*cart_filled).is_displayed() + print('ITEM IS IN CART!') + + diff --git a/features/steps/HW5.py b/features/steps/HW5.py new file mode 100644 index 000000000..a0807ad5b --- /dev/null +++ b/features/steps/HW5.py @@ -0,0 +1,30 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + +color_options = (By.CSS_SELECTOR, 'ul.a-declarative.a-button-list li') +curr_color = (By.CSS_SELECTOR, 'div.a-section span.selection') + + +@given('Open Target product {target_item} page') +def target_product_page(context, target_item): + context.driver.get(f'https://www.Amazon.com/dp/{target_item}') + + +@when('Verify color options') +def verify_color_options(context): + context.driver.find_element(*color_options).click() + + all_color_options = context.driver.find_elements(*color_options) + print('All colors:', all_color_options) + expected_colors = ['Aqua Blue Poppy', 'Black', 'Black White Animal Print', 'Bright Pink', 'Dark Blue White Petal', 'French Blue', 'Navy', 'Red Leafy Floral'] + + actual_colors = [] + for color in all_color_options[:8]: + color.click() + current_color = context.driver.find_element(*curr_color).text + print('Current color: ', current_color) + actual_colors += [current_color] + + assert expected_colors == actual_colors, f'Expected {expected_colors}, but got {actual_colors}' diff --git a/features/steps/HW6.py b/features/steps/HW6.py new file mode 100644 index 000000000..c88725419 --- /dev/null +++ b/features/steps/HW6.py @@ -0,0 +1,38 @@ +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as ec +from behave import given, when, then +from time import sleep + +privacy_link = (By.CSS_SELECTOR, 'a[href="https://policies.google.com/privacy"]') + + +@given('Open Amazon T&C page') +def open_page(context): + context.driver.get('https://www.aboutamazon.com/') + + +@when('Store original windows') +def store_window(context): + context.window_handles = context.driver.current_window_handle + + +@when('Click on Amazon Privacy Notice link') +def click_privacy_link(context): + context.driver.find_element(*privacy_link).click() + + +@when('Switch to the newly opened window') +def switch_to_window(context): + context.driver.switch_to.window(context.driver.window_handles[1]) + sleep(2) + + +@then('Verify Amazon Privacy Notice page is opened') +def verify_privacy_notice(context): + assert context.driver.current_window_handle == context.driver.window_handles[1] + +@then('User can close new window and switch back to original') +def switch_to_original_window(context): + context.driver.close() + context.driver.switch_to.window(context.driver.window_handles[0]) + diff --git a/features/steps/HW7.py b/features/steps/HW7.py new file mode 100644 index 000000000..7c0be555e --- /dev/null +++ b/features/steps/HW7.py @@ -0,0 +1,24 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then + +from time import sleep + +orders = (By.ID, "nav-orders") +empty = (By.ID, "div.sc-your-amazon-cart-is-empty") + + +@when('Click Amazon Orders link') +def click_amazon_orders_link(context): + context.browser.find_element(*orders).click() + sleep(2) + + +@then('Verify "Your Shopping Cart is empty." text present') +def verify_amazon_orders_text(context): + context.app.base_page.verify_partial_text("Your Amazon Cart is empty", *empty) + + +@when("Click on cart iconA") +def sign_in(context): + context.driver.find_element(By.ID, "nav-cart").click() + sleep(4) diff --git a/features/steps/HW8.py b/features/steps/HW8.py new file mode 100644 index 000000000..757a99160 --- /dev/null +++ b/features/steps/HW8.py @@ -0,0 +1,38 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + +@given('Open Target help page') +def open_target_help_page(context): + context.app.target_help_page.open_help_page() + + +@when('Select dropdown option') +def verify_dropdown_present(context): + context.app.target_help_page.dropdown_present() + + +@then('Verify page is correctly changed') +def verify_page_is_correct(context): + context.app.target_help_page.page_change() + + +@then('Enter username') +def enter_username(context): + context.app.target_help_page.enter_user() + + +@then('Enter Password') +def enter_password(context): + context.app.target_help_page.enter_pass() + + +@then('Click on sign in') +def click_sign_in(context): + context.app.target_help_page.click_sign_in() + + +@then('Verify error message appears') +def verify_error_message(context): + context.app.target_help_page.verify_error() diff --git a/features/steps/amazon_main_page_steps.py b/features/steps/amazon_main_page_steps.py new file mode 100644 index 000000000..16f957bb7 --- /dev/null +++ b/features/steps/amazon_main_page_steps.py @@ -0,0 +1,42 @@ +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() + sleep(2) + 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)}' \ No newline at end of file diff --git a/features/steps/amazon_search.py b/features/steps/amazon_search.py new file mode 100644 index 000000000..ef2e6fb87 --- /dev/null +++ b/features/steps/amazon_search.py @@ -0,0 +1,43 @@ +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}' + diff --git a/features/steps/bestsellers_page_steps.py b/features/steps/bestsellers_page_steps.py new file mode 100644 index 000000000..c4d1f3c0b --- /dev/null +++ b/features/steps/bestsellers_page_steps.py @@ -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() \ No newline at end of file diff --git a/features/steps/search_results_page_steps.py b/features/steps/search_results_page_steps.py new file mode 100644 index 000000000..7edc527cc --- /dev/null +++ b/features/steps/search_results_page_steps.py @@ -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}' \ No newline at end of file diff --git a/features/steps/sign_in_steps.py b/features/steps/sign_in_steps.py new file mode 100644 index 000000000..d31f7a174 --- /dev/null +++ b/features/steps/sign_in_steps.py @@ -0,0 +1,13 @@ +from selenium.webdriver.common.by import By +from behave import then +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from time import sleep + + + +@then('Verify Sign in page opened') +def verify_sign_in_opened(context): + wait = WebDriverWait(context.driver, 10) + context.driver.find_element(By.CSS_SELECTOR, "h1.a-spacing-small") + #context.driver.wait.until(EC.url_contains('ap/signin'), message='Signin URL did not open') \ No newline at end of file diff --git a/features/tests/Extras HW BDD.feature b/features/tests/Extras HW BDD.feature new file mode 100644 index 000000000..36f3da4e6 --- /dev/null +++ b/features/tests/Extras HW BDD.feature @@ -0,0 +1,12 @@ +# Created by 12405 at 5/23/2024 +Feature: Target look at products + # Enter feature description here + + Scenario: Target product presented + Given Open Target page + When Input dog into search bar + Then Verify product names and images displays + + Scenario: Amazon bestsellers + Given Open Amazon Bestsellers + When Click headers diff --git a/features/tests/HW3 BDD.feature b/features/tests/HW3 BDD.feature new file mode 100644 index 000000000..d0d76ca77 --- /dev/null +++ b/features/tests/HW3 BDD.feature @@ -0,0 +1,13 @@ +# Created by 12405 at 5/1/2024 +Feature: Target HW3 + + Scenario: Target cart check + Given Open Target page + When Click on cart icon + Then Verify cart page is present + + Scenario: Target sign in page + Given Open Target page + When Click on sign in icon + When Click on sign in button + Then Verify sign in page is present \ No newline at end of file diff --git a/features/tests/HW4 BDD.feature b/features/tests/HW4 BDD.feature new file mode 100644 index 000000000..e20a7cc5c --- /dev/null +++ b/features/tests/HW4 BDD.feature @@ -0,0 +1,20 @@ +# Created by 12405 at 5/3/2024 +Feature: Target Functions + # Enter feature description here + + Scenario: Target item search + Given Open Target site + When Input cup into search bar + Then Item results for for “cup” are displayed + + Scenario: Target Benefit Cells + Given Open Target benefit page + Then 10 Benefit cells populate + + Scenario: Target item search + Given Open Target site + When Input cup into search bar + Then Item results for for “cup” are displayed + When Add any item to cart + When Go to cart + Then Verify an item is in cart diff --git a/features/tests/HW5 BDD.feature b/features/tests/HW5 BDD.feature new file mode 100644 index 000000000..03509ff34 --- /dev/null +++ b/features/tests/HW5 BDD.feature @@ -0,0 +1,6 @@ +# Created by 12405 at 5/6/2024 +Feature: Verify colors + + Scenario: Target product color options + Given Open Target product B082ZSMY4M page + When Verify color options diff --git a/features/tests/HW6 BDD.feature b/features/tests/HW6 BDD.feature new file mode 100644 index 000000000..7ab498b40 --- /dev/null +++ b/features/tests/HW6 BDD.feature @@ -0,0 +1,10 @@ +# Created by 12405 at 5/7/2024 + Feature: Amazon privacy page + + Scenario: User can open and close Amazon Privacy Notice + Given Open Amazon T&C page + When Store original windows + And Click on Amazon Privacy Notice link + And Switch to the newly opened window + Then Verify Amazon Privacy Notice page is opened + And User can close new window and switch back to original diff --git a/features/tests/HW7.feature b/features/tests/HW7.feature new file mode 100644 index 000000000..082112853 --- /dev/null +++ b/features/tests/HW7.feature @@ -0,0 +1,12 @@ +# Created by 12405 at 5/12/2024 +Feature: Amazon finds + +Scenario: Logged out user sees Sign in page when clicking Orders + Given Open Amazon page + When Click Amazon Orders link + Then Verify Sign in page opened + +Scenario: 'Your Shopping Cart is empty' shown if no product added + Given Open Amazon page + When Click on cart iconA + Then Verify "Your Shopping Cart is empty." text present \ No newline at end of file diff --git a/features/tests/HW8.feature b/features/tests/HW8.feature new file mode 100644 index 000000000..62a223c85 --- /dev/null +++ b/features/tests/HW8.feature @@ -0,0 +1,18 @@ +# Created by 12405 at 5/14/2024 +Feature: Target help page selects + # Enter feature description here + + Scenario: Target help dropdown + Given Open Target help page + When Select dropdown option + Then Verify page is correctly changed + + Scenario: + Given Open Target page + When Click on sign in icon + When Click on sign in button + Then Verify sign in page is present + And Enter username + And Enter Password + And Click on sign in + Then Verify error message appears \ No newline at end of file diff --git a/features/tests/amazon_main.feature b/features/tests/amazon_main.feature new file mode 100644 index 000000000..011eb14c5 --- /dev/null +++ b/features/tests/amazon_main.feature @@ -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 \ No newline at end of file diff --git a/features/tests/amazon_search.feature b/features/tests/amazon_search.feature new file mode 100644 index 000000000..fc02c76ab --- /dev/null +++ b/features/tests/amazon_search.feature @@ -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 + Then Search results for 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 \ No newline at end of file diff --git a/features/tests/product_details.feature b/features/tests/product_details.feature new file mode 100644 index 000000000..31264e810 --- /dev/null +++ b/features/tests/product_details.feature @@ -0,0 +1,6 @@ +# Created by 12405 at 5/12/2024 +Feature: # Enter feature name here + # Enter feature description here + + Scenario: # Enter scenario name here + # Enter steps here \ No newline at end of file diff --git a/features/tests/sign_in.feature b/features/tests/sign_in.feature new file mode 100644 index 000000000..e1c428707 --- /dev/null +++ b/features/tests/sign_in.feature @@ -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 \ No newline at end of file diff --git a/pages/__init__.py b/pages/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pages/base_page.py b/pages/base_page.py new file mode 100644 index 000000000..ed2d2cb15 --- /dev/null +++ b/pages/base_page.py @@ -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)) \ No newline at end of file diff --git a/pages/bestsellers_page.py b/pages/bestsellers_page.py new file mode 100644 index 000000000..7f8c6b291 --- /dev/null +++ b/pages/bestsellers_page.py @@ -0,0 +1,22 @@ +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}' diff --git a/pages/main_page.py b/pages/main_page.py new file mode 100644 index 000000000..89498b2ab --- /dev/null +++ b/pages/main_page.py @@ -0,0 +1,14 @@ +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) diff --git a/pages/search_results_page.py b/pages/search_results_page.py new file mode 100644 index 000000000..0ed58cd91 --- /dev/null +++ b/pages/search_results_page.py @@ -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) \ No newline at end of file diff --git a/pages/target_help_page.py b/pages/target_help_page.py new file mode 100644 index 000000000..ab6b49e82 --- /dev/null +++ b/pages/target_help_page.py @@ -0,0 +1,27 @@ +from selenium.webdriver.common.by import By +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.support.ui import Select +from pages.base_page import Page +from time import sleep + + +class TargetHelpPage(Page): + dropdown = (By.CSS_SELECTOR, '[onchange="changeItem()"]') + dif_page = (By.ID, 'ui-id-1') + + def open_help_page(self): + self.driver.get('https://help.target.com/help/SubCategoryArticle') + + def dropdown_present(self): + drop = self.find_element(*self.dropdown) + select = Select(drop) + select.select_by_value('Orders & Purchases') + + + def dropdown_select(self): + self.driver.find_element(*self.dropdown).click() + self.driver.find_element(*self.dropdown).click() + + def page_change(self): + self.driver.find_element(*self.dif_page).is_displayed() + diff --git a/pages/target_sign_in.py b/pages/target_sign_in.py new file mode 100644 index 000000000..a85d0c66a --- /dev/null +++ b/pages/target_sign_in.py @@ -0,0 +1,28 @@ +from selenium.webdriver.common.by import By +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.support.ui import Select +from pages.base_page import Page +from time import sleep + + +class TargetSignIn(Page): + user = (By.ID, 'username') + pas = (By.ID, 'password') + login = (By.ID, 'login') + error = (By.CSS_SELECTOR, 'div.styles__AlertDisplayStyles-sc-vw2fsn-0') + + def enter_user(self, username): + self.driver.find_element(*self.user).send_keys('gieks@bdfjie.com') + + + def enter_pass(self, password): + self.driver.find_element(*self.pas).send_keys('https://www.target.com/login?client_id') + + + def click_sign_in(self): + self.driver.find_element(*self.login).click() + + + def verify_error(self): + self.driver.find_element(*self.error).is_displayed() + diff --git a/sample_script.py b/sample_script.py index 23d64fc06..905b589e8 100755 --- a/sample_script.py +++ b/sample_script.py @@ -18,7 +18,7 @@ # populate search field search = driver.find_element(By.NAME, 'q') search.clear() -search.send_keys('Car') +search.send_keys('air') # wait for 4 sec sleep(4) @@ -27,7 +27,7 @@ driver.find_element(By.NAME, 'btnK').click() # verify search results -assert 'car' in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}" +assert 'air' in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}" print('Test Passed') driver.quit() diff --git a/support/logger.py b/support/logger.py new file mode 100644 index 000000000..b8bd5f643 --- /dev/null +++ b/support/logger.py @@ -0,0 +1,25 @@ + +import logging + +from selenium.webdriver.support.events import AbstractEventListener + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +handler = logging.FileHandler('./test_automation.log') +handler.setLevel(logging.DEBUG) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) + + +class MyListener(AbstractEventListener): + logger = logger + + def before_find(self, by, value, driver): + logger.info(f"Searching by {by} '{value}'...") + + def after_find(self, by, value, driver): + logger.info(f"Found by {by} '{value}'") + + def on_exception(self, exception, driver): + logger.error(exception) diff --git a/test-scriprt.py b/test-scriprt.py new file mode 100644 index 000000000..8ac1f25fb --- /dev/null +++ b/test-scriprt.py @@ -0,0 +1,14 @@ +from selenium.webdriver.common.by import By +from selenium import webdriver +import json +import webdriver_manager + + +executor_object = { + 'action': 'setSessionName', + 'arguments': { + 'name': "" + } +} +browserstack_executor = 'browserstack_executor: {}'.format(json.dumps(executor_object)) +webdriver.execute_script(browserstack_executor) \ No newline at end of file diff --git a/test_results/0b8bb850-b51d-42da-931e-1009805ce77e-result.json b/test_results/0b8bb850-b51d-42da-931e-1009805ce77e-result.json new file mode 100644 index 000000000..56ff25254 --- /dev/null +++ b/test_results/0b8bb850-b51d-42da-931e-1009805ce77e-result.json @@ -0,0 +1 @@ +{"name": "User can search for coffee", "status": "broken", "statusDetails": {"message": "selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: [id=\"twotabsearchtextbox\"]; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception\nStacktrace:\nWebDriverError@chrome://remote/content/shared/webdriver/Errors.jsm:181:5\nNoSuchElementError@chrome://remote/content/shared/webdriver/Errors.jsm:393:5\nelement.find/", + 'reason': "" + } +} +browserstack_executor = 'browserstack_executor: {}'.format(json.dumps(executor_object)) +webdriver.execute_script(browserstack_executor).maximize_window()