From 386babe23b0a164afcd18b24309b599b3f4705b1 Mon Sep 17 00:00:00 2001 From: Justin Pauge Date: Fri, 6 Feb 2026 14:22:34 -0800 Subject: [PATCH 1/4] lesson 1 hw --- file.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 file.txt diff --git a/file.txt b/file.txt new file mode 100644 index 000000000..e69de29bb From fcb162adb47caaeed8bee3a99811f55361c11d2d Mon Sep 17 00:00:00 2001 From: Justin Pauge Date: Sun, 8 Feb 2026 12:14:18 -0800 Subject: [PATCH 2/4] Initial commit --- css_selectors_hw3.py | 45 +++++++++++++++++ features/locators_hw2.py | 42 ++++++++++++++++ features/steps/product_search.py | 1 - features/steps/target_search_steps_hw3.py | 60 +++++++++++++++++++++++ features/steps/target_search_steps_hw4.py | 47 ++++++++++++++++++ features/steps/target_search_steps_hw5.py | 38 ++++++++++++++ features/steps/target_search_steps_hw6.py | 43 ++++++++++++++++ features/target_search_script_hw2.py | 35 +++++++++++++ features/tests/target_search_hw3.feature | 19 +++++++ features/tests/target_search_hw4.feature | 15 ++++++ features/tests/target_search_hw5.feature | 7 +++ 11 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 css_selectors_hw3.py create mode 100644 features/locators_hw2.py create mode 100644 features/steps/target_search_steps_hw3.py create mode 100644 features/steps/target_search_steps_hw4.py create mode 100644 features/steps/target_search_steps_hw5.py create mode 100644 features/steps/target_search_steps_hw6.py create mode 100644 features/target_search_script_hw2.py create mode 100644 features/tests/target_search_hw3.feature create mode 100644 features/tests/target_search_hw4.feature create mode 100644 features/tests/target_search_hw5.feature diff --git a/css_selectors_hw3.py b/css_selectors_hw3.py new file mode 100644 index 000000000..fe69104cd --- /dev/null +++ b/css_selectors_hw3.py @@ -0,0 +1,45 @@ +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 + +# get the path to the ChromeDriver executable +driver_path = ChromeDriverManager().install() + +# create a new Chrome browser instance +service = Service(driver_path) +driver = webdriver.Chrome() +driver.maximize_window() + +# open the url +driver.get('https://www.amazon.com/') + +# CSS, by ID => # +driver.find_element(By.CSS_SELECTOR, '#twotabsearchtextbox') # (By.ID, 'twotabsearchtextbox') +# CSS, by ID and tag +driver.find_element(By.CSS_SELECTOR, 'input#twotabsearchtextbox') + +# CSS, class => . +driver.find_element(By.CSS_SELECTOR, '.icp-nav-flag-us') +driver.find_element(By.CSS_SELECTOR, '.icp-nav-flag-us.icp-nav-flag') +driver.find_element(By.CSS_SELECTOR, '.icp-nav-flag.icp-nav-flag-us') +# CSS, class and tag +driver.find_element(By.CSS_SELECTOR, 'span.icp-nav-flag.icp-nav-flag-us') +# CSS, tag, id, class +driver.find_element(By.CSS_SELECTOR, "input#twotabsearchtextbox.nav-progressive-attribute") + +# CSS, attributes => [] +driver.find_element(By.CSS_SELECTOR, "[aria-label='Search Amazon']") +driver.find_element(By.CSS_SELECTOR, "[name='field-keywords']") +driver.find_element(By.CSS_SELECTOR, "[name='field-keywords'][aria-label='Search Amazon']") +driver.find_element(By.CSS_SELECTOR, "input[name='field-keywords'][aria-label='Search Amazon']") + +driver.find_element(By.CSS_SELECTOR, ".nav-input[name='field-keywords'][aria-label='Search Amazon']") +driver.find_element(By.CSS_SELECTOR, "input.nav-input[name='field-keywords'][aria-label='Search Amazon']") + +# CSS, attributes, contains => *= [] +driver.find_element(By.CSS_SELECTOR, "[aria-label*='Amazon']") +driver.find_element(By.CSS_SELECTOR, "[data-test='accountNav-signIn']") +driver.find_element(By.CSS_SELECTOR, "[class*='styles_ndsBaseButton'][class*='styles_ndsButtonPrimary']") +\ \ No newline at end of file diff --git a/features/locators_hw2.py b/features/locators_hw2.py new file mode 100644 index 000000000..552942a50 --- /dev/null +++ b/features/locators_hw2.py @@ -0,0 +1,42 @@ +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 + +# get the path to the ChromeDriver executable +driver_path = ChromeDriverManager().install() + +# create a new Chrome browser instance +service = Service(driver_path) +driver = webdriver.Chrome() +driver.maximize_window() + +# open the url +driver.get('https://www.amazon.com/') + +# By ID +driver.find_element(By.ID, 'twotabsearchtextbox') +driver.find_element(By.ID, 'nav-search-submit-button') + +# By Xpath +driver.find_element(By.XPATH, "//input[@aria-label='Search Amazon']") # //tag[@attr='value'] +driver.find_element(By.XPATH, "//input[@role='searchbox']") + +# By Xpath, multiple attributes +driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords']") +driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords' and @role='searchbox']") +driver.find_element(By.XPATH, "//input[@name='field-keywords' and @tabindex='0' and @role='searchbox']") + +# By Xpath, any tag +driver.find_element(By.XPATH, "//*[@aria-label='Search Amazon']") + +# By Xpath, using text +driver.find_element(By.XPATH, "//a[text()='Best Sellers']") +driver.find_element(By.XPATH, "//a[text()='Best Sellers' and @class='nav-a ']") +driver.find_element(By.XPATH, "//a[@class='nav-a ' and text()='Best Sellers']") + +# partial text match +driver.find_element(By.XPATH, "//h2[contains(text(), 'Luxury')]") +# partial attr match +driver.find_element(By.XPATH, "//select[contains(@class, 'nav-search-dropdown')]") \ No newline at end of file diff --git a/features/steps/product_search.py b/features/steps/product_search.py index 4e142cb40..1ed153f1a 100755 --- a/features/steps/product_search.py +++ b/features/steps/product_search.py @@ -2,7 +2,6 @@ from behave import given, when, then from time import sleep - SEARCH_INPUT = (By.NAME, 'q') SEARCH_SUBMIT = (By.NAME, 'btnK') diff --git a/features/steps/target_search_steps_hw3.py b/features/steps/target_search_steps_hw3.py new file mode 100644 index 000000000..120c6c8d7 --- /dev/null +++ b/features/steps/target_search_steps_hw3.py @@ -0,0 +1,60 @@ + +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + +CART_ICON = (By.CSS_SELECTOR, 'a[data-test="@web/CartLink"]') +SIGN_IN_ICON = (By.CSS_SELECTOR, 'a[id="account-sign-in"]') + + +# @given('Open target main page') +# def open_target(context): +# context.driver.get('https://www.target.com/') +# sleep(2) +# + +# @when('Search for {search_text}') +# def search_product(context, search_text): +# # find search field and enter text +# context.driver.find_element(By.ID, 'search').send_keys(search_text) +# # click search +# context.driver.find_element(By.XPATH, "//button[@data-test='@web/Search/SearchButton']").click() +# # wait for the page with search results to load +# sleep(6) + + +@then('Verify correct search results shown') +def verify_search_results(context): + expected_text = 'car' + actual_text = context.driver.find_element(By.XPATH, "//div[@data-test='resultsHeading']").text + assert expected_text in actual_text, f'Expected {expected_text} ot in actual {actual_text}' + + +# @when('Click on Cart icon') +# def click_cart(context): +# context.driver.find_element(*CART_ICON).click() +# sleep(5) + + +@then('Verify Empty cart message is shown') +def verify_empty_cart(context): + expected_result = 'Your cart is empty' + actual_result = context.driver.find_element(By.CSS_SELECTOR, "[data-test='boxEmptyMsg']").text + assert expected_result == actual_result, f'Expected {expected_result} did not match actual {actual_result}' + sleep(5) + + +@when('Click Sign in') +def click_sign_in(context): + context.driver.find_element(*SIGN_IN_ICON).click() + sleep(2) + + +@then('Verify Sign in Form opens') +def verify_sign_in(context): + context.driver.find_element(By.XPATH, "//*[@data-test='accountNav-signIn']").click() + sleep(3) + expected = 'Sign in or create account' + actual = context.driver.find_element(By.XPATH, "//h1[contains(@class, 'styles_ndsHeading')]").text + assert expected == actual, f'Expected {expected} did not match actual {actual}' + sleep(5) diff --git a/features/steps/target_search_steps_hw4.py b/features/steps/target_search_steps_hw4.py new file mode 100644 index 000000000..81e0d3143 --- /dev/null +++ b/features/steps/target_search_steps_hw4.py @@ -0,0 +1,47 @@ + +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + +CART_ICON = (By.CSS_SELECTOR, 'a[data-test="@web/CartLink"]') +CART_SUMMARY = (By.XPATH, "//div[./span[contains(text(), 'subtotal')]]") +BENEFIT_CELL = (By.CSS_SELECTOR, '[class="cell-item-content"]') +ADD_CART_BUTTON = (By.CSS_SELECTOR, '[id*="addToCartButtonOrTextIdFor"]') +ADD_CART_BUTTON_2 = (By.CSS_SELECTOR, '[data-test="orderPickupButton"]') +ADD_CART_BUTTON_3 = (By.CSS_SELECTOR, '[href="/cart"]') +CART_ITEM_TITLE = (By.CSS_SELECTOR, "[data-test='cartItem-title']") + + +@given('Open Target circle page') +def open_cart(context): + context.driver.get('https://www.target.com/circle') + sleep(3) + + +@then('Verify 10 or more benefit cells') +def verify_benefit_cells(context): + actual_benefit_cells_len = context.driver.find_elements(*BENEFIT_CELL) + print(f'Benefit cells: {len(actual_benefit_cells_len)}') + assert len(actual_benefit_cells_len) >= 10, f'Benefit cells count {len(actual_benefit_cells_len)} should be greater or equal to 10' + + +@when('Add item to cart') +def add_to_cart(context): + sleep(10) + context.driver.find_element(*ADD_CART_BUTTON).click() + sleep(3) + context.driver.find_element(*ADD_CART_BUTTON_2).click() + sleep(2) + context.driver.find_element(*ADD_CART_BUTTON_3).click() + + +@then('Verify {item} in cart') +def verify_product_name(context, item): + sleep(5) + product_name_in_cart = context.driver.find_element(*CART_ITEM_TITLE).text + print('Name in cart: ', product_name_in_cart) + assert item in product_name_in_cart.lower(), \ + f'Expected {item} did not match {product_name_in_cart}' + + + diff --git a/features/steps/target_search_steps_hw5.py b/features/steps/target_search_steps_hw5.py new file mode 100644 index 000000000..adacdc67e --- /dev/null +++ b/features/steps/target_search_steps_hw5.py @@ -0,0 +1,38 @@ + +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + +## aria-label="color, +COLOR_OPTIONS = (By.CSS_SELECTOR, 'ul li a[aria-label*="color"]') +SELECTED_COLOR = (By.CSS_SELECTOR, '[aria-label*="color 39063"]') + + +# @when('Click on each color') +# def click_on_color(context): +# context.driver.find_elements(By.CSS_SELECTOR, '.color').click() +# sleep(2) + + +@given('Open target product {product_id} page') +def open_target(context, product_id): + context.driver.get(f'https://www.target.com/p/{product_id}') + sleep(8) + + +@then('Click through colors and verify selection') +def verify_color(context): + sleep(8) + expected_colors = ['black', 'light grey', 'navy', 'sage'] + actual_colors = [] + colors = context.driver.find_elements(*COLOR_OPTIONS) + for color in colors: + color.click() + selected_color = context.driver.find_element(*SELECTED_COLOR).text # 'Color\nBlack' + print('Current color', selected_color) + selected_color = selected_color.split('color\n39063-')[1] # remove 'Color\n' part, keep Black' + sleep(3) + actual_colors.append(selected_color) + print(actual_colors) + + assert expected_colors == actual_colors, f'Expected {expected_colors} did not match actual {actual_colors}' \ No newline at end of file diff --git a/features/steps/target_search_steps_hw6.py b/features/steps/target_search_steps_hw6.py new file mode 100644 index 000000000..f0e33390c --- /dev/null +++ b/features/steps/target_search_steps_hw6.py @@ -0,0 +1,43 @@ + +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + +CART_SUMMARY = (By.XPATH, "//div[./span[contains(text(), 'subtotal')]]") +CART_ITEM_TITLE = (By.CSS_SELECTOR, "[data-test='cartItem-title']") + + +@given('Open target.com') +def open_target(context): + # context.driver.get('https://www.target.com/') + context.app.main_page.open_main_page() + +# @when('Click on Cart icon') +# def open_cart(context): +# # context.driver.get('https://www.target.com/cart') +# context.app.cart_page.open_cart() + + +@then("Verify 'Your cart is empty' message is shown") +def verify_empty_cart(context): + sleep(5) + context.app.cart_page.verify_empty_cart() + + + + + +# @then('Verify cart has correct product') +# def verify_product_name(context): +# # context.product_name => stored before +# product_name_in_cart = context.driver.find_element(*CART_ITEM_TITLE).text +# print('Name in cart: ', product_name_in_cart) +# assert context.product_name[:20] == product_name_in_cart[:20], \ +# f'Expected {context.product_name[:20]} did not match {product_name_in_cart[:20]}' +# +# +# @then('Verify cart has {amount} item(s)') +# def verify_cart_items(context, amount): +# cart_summary = context.driver.find_element(*CART_SUMMARY).text +# assert f'{amount} item' in cart_summary, f"Expected {amount} items but got {cart_summary}" diff --git a/features/target_search_script_hw2.py b/features/target_search_script_hw2.py new file mode 100644 index 000000000..e94b453d1 --- /dev/null +++ b/features/target_search_script_hw2.py @@ -0,0 +1,35 @@ +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 + +# get the path to the ChromeDriver executable +driver_path = ChromeDriverManager().install() + +# create a new Chrome browser instance +service = Service(driver_path) +driver = webdriver.Chrome() +driver.maximize_window() + +# open the url +driver.get('https://www.target.com/') + +driver.find_element(By.ID, 'search').send_keys('tea') +driver.find_element(By.XPATH, "//button[@data-test='@web/Search/SearchButton']").click() +sleep(6) + +# verification: +# by finding 1 element +# driver.find_element(By.XPATH, "//div[@data-test='lp-resultsCount']") +# print('Test case passed') + +# by checking text +actual_text = driver.find_element(By.XPATH, "//div[@data-test='lp-resultsCount']").text +expected_text = 'tea' + +assert expected_text in actual_text, f'Error. Text {expected_text} not in {actual_text}' +print('Test case passed') + +# Note: please do not use if/else for verification, you test case must fail with an Exception if a feature is broken +# sleep(10) \ No newline at end of file diff --git a/features/tests/target_search_hw3.feature b/features/tests/target_search_hw3.feature new file mode 100644 index 000000000..8b17b026a --- /dev/null +++ b/features/tests/target_search_hw3.feature @@ -0,0 +1,19 @@ +Feature: Target search test cases + + +##Empty cart message + Scenario: User can verify cart is empty + Given Open target main page + When Click on Cart icon + Then Verify Empty cart message is shown + + +## Verify log out to log in + Scenario: Logged out User can navigate to sign in page + Given Open target main page + When Click Sign in + Then Verify Sign in Form opens + + + + diff --git a/features/tests/target_search_hw4.feature b/features/tests/target_search_hw4.feature new file mode 100644 index 000000000..1a453cc92 --- /dev/null +++ b/features/tests/target_search_hw4.feature @@ -0,0 +1,15 @@ +Feature: Update Target search test cases and add Behave variables + + +##Open Target Circle and verify 10 benefit cells + Scenario: User can open Target Circle with 10 benefit cells + Given Open Target circle page + Then Verify 10 or more benefit cells + + +## Add a Target product to cart And Verify it is there + Scenario: Add product to cart + Given Open target main page + When Search for coffee + When Add item to cart + Then Verify coffee in cart \ No newline at end of file diff --git a/features/tests/target_search_hw5.feature b/features/tests/target_search_hw5.feature new file mode 100644 index 000000000..f9b4fae40 --- /dev/null +++ b/features/tests/target_search_hw5.feature @@ -0,0 +1,7 @@ +Feature: Update Target search test cases and add Behave variables + + +##Search for color of product, click each color, verify color selected + Scenario: Add product to cart + Given Open target product {x-ray-men-s-cable-knit-cowl-neck-sweater/-/A-1001689658} page + Then Click through colors and verify selection From d2a582cc83ef398f4b1910de7902300aed60105b Mon Sep 17 00:00:00 2001 From: Justin Pauge Date: Sun, 8 Feb 2026 22:19:06 -0800 Subject: [PATCH 3/4] hw 2, 3, 4, 5, 6 together --- app/__init__.py | 0 app/application.py | 16 ++++ .../css_selectors_hw3.py | 0 features/environment.py | 4 +- features/locators_hw2.py | 77 ++++++++++++++----- features/steps/target_search_steps_hw3.py | 36 ++++----- features/steps/target_search_steps_hw4.py | 18 ++--- features/steps/target_search_steps_hw5.py | 17 ++-- features/tests/target_search_hw4.feature | 4 +- features/tests/target_search_hw5.feature | 2 +- features/tests/target_search_hw6.feature | 7 ++ pages/__init__.py | 0 pages/base_page.py | 19 +++++ pages/cart_page.py | 11 +++ pages/header.py | 16 ++++ pages/main_page.py | 6 ++ pages/search_results_page.py | 11 +++ 17 files changed, 185 insertions(+), 59 deletions(-) create mode 100644 app/__init__.py create mode 100644 app/application.py rename css_selectors_hw3.py => features/css_selectors_hw3.py (100%) create mode 100644 features/tests/target_search_hw6.feature create mode 100644 pages/__init__.py create mode 100644 pages/base_page.py create mode 100644 pages/cart_page.py create mode 100644 pages/header.py create mode 100644 pages/main_page.py create mode 100644 pages/search_results_page.py 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..fbc6a61c7 --- /dev/null +++ b/app/application.py @@ -0,0 +1,16 @@ +from pages.header import Header +from pages.main_page import MainPage +from pages.search_results_page import SearchResultsPage +from pages.cart_page import CartPage + + +class Application: + + + def __init__(self, driver): + + + self.main_page = MainPage(driver) + self.header = Header(driver) + self.search_results_page = SearchResultsPage(driver) + self.cart_page = CartPage(driver) diff --git a/css_selectors_hw3.py b/features/css_selectors_hw3.py similarity index 100% rename from css_selectors_hw3.py rename to features/css_selectors_hw3.py diff --git a/features/environment.py b/features/environment.py index 1275460a0..80a116b96 100755 --- a/features/environment.py +++ b/features/environment.py @@ -1,7 +1,7 @@ from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager - +from app.application import Application def browser_init(context): """ @@ -11,6 +11,8 @@ def browser_init(context): service = Service(driver_path) context.driver = webdriver.Chrome(service=service) + context.app = Application(context.driver) + context.driver.maximize_window() context.driver.implicitly_wait(4) diff --git a/features/locators_hw2.py b/features/locators_hw2.py index 552942a50..7775da806 100644 --- a/features/locators_hw2.py +++ b/features/locators_hw2.py @@ -13,30 +13,65 @@ driver.maximize_window() # open the url -driver.get('https://www.amazon.com/') +driver.get('https://www.amazon.com/ap/signin?openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.amazon.com%2Fgp%2Fcart%2Fview.html%3Fref_%3Dnav_ya_signin&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.assoc_handle=usflex&openid.mode=checkid_setup&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0') -# By ID -driver.find_element(By.ID, 'twotabsearchtextbox') -driver.find_element(By.ID, 'nav-search-submit-button') +sleep(10) -# By Xpath -driver.find_element(By.XPATH, "//input[@aria-label='Search Amazon']") # //tag[@attr='value'] -driver.find_element(By.XPATH, "//input[@role='searchbox']") +####LOCATORS +#Amazon Logo +driver.find_element(By.CSS_SELECTOR, '[class="a-icon a-icon-logo"]') -# By Xpath, multiple attributes -driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords']") -driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords' and @role='searchbox']") -driver.find_element(By.XPATH, "//input[@name='field-keywords' and @tabindex='0' and @role='searchbox']") +#Email field +driver.find_element(By.CSS_SELECTOR,'[class="a-input-text"]') -# By Xpath, any tag -driver.find_element(By.XPATH, "//*[@aria-label='Search Amazon']") +#Continue button +driver.find_element(By.CSS_SELECTOR, '[class="a-button-input"]') -# By Xpath, using text -driver.find_element(By.XPATH, "//a[text()='Best Sellers']") -driver.find_element(By.XPATH, "//a[text()='Best Sellers' and @class='nav-a ']") -driver.find_element(By.XPATH, "//a[@class='nav-a ' and text()='Best Sellers']") +#Conditions of use link +driver.find_element(By.CSS_SELECTOR, 'a[href*="/gp/help/customer/display.html/ref=ap_signin_notification_condition_of_use"]') -# partial text match -driver.find_element(By.XPATH, "//h2[contains(text(), 'Luxury')]") -# partial attr match -driver.find_element(By.XPATH, "//select[contains(@class, 'nav-search-dropdown')]") \ No newline at end of file +#Privacy Notice link +driver.find_element(By.CSS_SELECTOR, 'a[href*="/gp/help/customer/display.html/ref=ap_signin_notification_privacy_notice"]') + +#Need help link +driver.find_element(By.CSS_SELECTOR, '[class="a-size-base a-link-normal"]') + + +driver.quit() + + + + + + + + + + +# +# +# # By ID +# driver.find_element(By.ID, 'twotabsearchtextbox') +# driver.find_element(By.ID, 'nav-search-submit-button') +# +# # By Xpath +# driver.find_element(By.XPATH, "//input[@aria-label='Search Amazon']") # //tag[@attr='value'] +# driver.find_element(By.XPATH, "//input[@role='searchbox']") +# +# # By Xpath, multiple attributes +# driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords']") +# driver.find_element(By.XPATH, "//input[@tabindex='0' and @name='field-keywords' and @role='searchbox']") +# driver.find_element(By.XPATH, "//input[@name='field-keywords' and @tabindex='0' and @role='searchbox']") +# +# # By Xpath, any tag +# driver.find_element(By.XPATH, "//*[@aria-label='Search Amazon']") +# +# # By Xpath, using text +# driver.find_element(By.XPATH, "//a[text()='Best Sellers']") +# driver.find_element(By.XPATH, "//a[text()='Best Sellers' and @class='nav-a ']") +# driver.find_element(By.XPATH, "//a[@class='nav-a ' and text()='Best Sellers']") +# +# # partial text match +# driver.find_element(By.XPATH, "//h2[contains(text(), 'Luxury')]") +# # partial attr match +# driver.find_element(By.XPATH, "//select[contains(@class, 'nav-search-dropdown')]") \ No newline at end of file diff --git a/features/steps/target_search_steps_hw3.py b/features/steps/target_search_steps_hw3.py index 120c6c8d7..0c4b067d6 100644 --- a/features/steps/target_search_steps_hw3.py +++ b/features/steps/target_search_steps_hw3.py @@ -7,20 +7,20 @@ SIGN_IN_ICON = (By.CSS_SELECTOR, 'a[id="account-sign-in"]') -# @given('Open target main page') -# def open_target(context): -# context.driver.get('https://www.target.com/') -# sleep(2) -# - -# @when('Search for {search_text}') -# def search_product(context, search_text): -# # find search field and enter text -# context.driver.find_element(By.ID, 'search').send_keys(search_text) -# # click search -# context.driver.find_element(By.XPATH, "//button[@data-test='@web/Search/SearchButton']").click() -# # wait for the page with search results to load -# sleep(6) +@given('Open target main page') +def open_target(context): + context.driver.get('https://www.target.com/') + sleep(2) + + +@when('Search for {search_text}') +def search_product(context, search_text): + # find search field and enter text + context.driver.find_element(By.ID, 'search').send_keys(search_text) + # click search + context.driver.find_element(By.XPATH, "//button[@data-test='@web/Search/SearchButton']").click() + # wait for the page with search results to load + sleep(6) @then('Verify correct search results shown') @@ -30,10 +30,10 @@ def verify_search_results(context): assert expected_text in actual_text, f'Expected {expected_text} ot in actual {actual_text}' -# @when('Click on Cart icon') -# def click_cart(context): -# context.driver.find_element(*CART_ICON).click() -# sleep(5) +@when('Click on Cart icon') +def click_cart(context): + context.driver.find_element(*CART_ICON).click() + sleep(5) @then('Verify Empty cart message is shown') diff --git a/features/steps/target_search_steps_hw4.py b/features/steps/target_search_steps_hw4.py index 81e0d3143..57485afb2 100644 --- a/features/steps/target_search_steps_hw4.py +++ b/features/steps/target_search_steps_hw4.py @@ -5,9 +5,9 @@ CART_ICON = (By.CSS_SELECTOR, 'a[data-test="@web/CartLink"]') CART_SUMMARY = (By.XPATH, "//div[./span[contains(text(), 'subtotal')]]") -BENEFIT_CELL = (By.CSS_SELECTOR, '[class="cell-item-content"]') +BENEFIT_CELL = (By.CSS_SELECTOR, '[class="sc-3e90527f-1 colamC storycard--text"') ADD_CART_BUTTON = (By.CSS_SELECTOR, '[id*="addToCartButtonOrTextIdFor"]') -ADD_CART_BUTTON_2 = (By.CSS_SELECTOR, '[data-test="orderPickupButton"]') +ADD_CART_BUTTON_2 = (By.CSS_SELECTOR, '[aria-label="Fulfillment"] [id*="addToCartButtonOrTextId') ADD_CART_BUTTON_3 = (By.CSS_SELECTOR, '[href="/cart"]') CART_ITEM_TITLE = (By.CSS_SELECTOR, "[data-test='cartItem-title']") @@ -18,20 +18,20 @@ def open_cart(context): sleep(3) -@then('Verify 10 or more benefit cells') -def verify_benefit_cells(context): - actual_benefit_cells_len = context.driver.find_elements(*BENEFIT_CELL) - print(f'Benefit cells: {len(actual_benefit_cells_len)}') - assert len(actual_benefit_cells_len) >= 10, f'Benefit cells count {len(actual_benefit_cells_len)} should be greater or equal to 10' +@then('Verify two storycards') +def verify_storycards(context): + actual_storycards_len = context.driver.find_elements(*BENEFIT_CELL) + print(f'Storycards: {len(actual_storycards_len)}') + assert len(actual_storycards_len) == 2, f'Story cards count {len(actual_storycards_len)} should equal 2' @when('Add item to cart') def add_to_cart(context): sleep(10) context.driver.find_element(*ADD_CART_BUTTON).click() - sleep(3) + sleep(10) context.driver.find_element(*ADD_CART_BUTTON_2).click() - sleep(2) + sleep(5) context.driver.find_element(*ADD_CART_BUTTON_3).click() diff --git a/features/steps/target_search_steps_hw5.py b/features/steps/target_search_steps_hw5.py index adacdc67e..6dee3018d 100644 --- a/features/steps/target_search_steps_hw5.py +++ b/features/steps/target_search_steps_hw5.py @@ -4,9 +4,9 @@ from time import sleep ## aria-label="color, -COLOR_OPTIONS = (By.CSS_SELECTOR, 'ul li a[aria-label*="color"]') -SELECTED_COLOR = (By.CSS_SELECTOR, '[aria-label*="color 39063"]') +COLOR_OPTIONS = (By.CSS_SELECTOR, 'ul li[class="styles_ndsCarouselItem__dnUkr"]') +SELECTED_COLOR = (By.CSS_SELECTOR, '[data-test="@web/VariationComponent"] [class*="styles_headerWrapper"]') # @when('Click on each color') # def click_on_color(context): @@ -20,17 +20,20 @@ def open_target(context, product_id): sleep(8) + @then('Click through colors and verify selection') def verify_color(context): - sleep(8) - expected_colors = ['black', 'light grey', 'navy', 'sage'] + sleep(5) + expected_colors = ['Berry Pink', 'Charcoal Gray', 'Light Beige'] actual_colors = [] colors = context.driver.find_elements(*COLOR_OPTIONS) - for color in colors: + print(len(colors)) + for color in colors[0:3]: + sleep(5) color.click() - selected_color = context.driver.find_element(*SELECTED_COLOR).text # 'Color\nBlack' + selected_color = context.driver.find_element(*SELECTED_COLOR).text[1] # 'Color\nBlack' print('Current color', selected_color) - selected_color = selected_color.split('color\n39063-')[1] # remove 'Color\n' part, keep Black' + #selected_color = selected_color.split('color\n39063-')[1] # remove 'Color\n' part, keep Black' sleep(3) actual_colors.append(selected_color) print(actual_colors) diff --git a/features/tests/target_search_hw4.feature b/features/tests/target_search_hw4.feature index 1a453cc92..a11964f85 100644 --- a/features/tests/target_search_hw4.feature +++ b/features/tests/target_search_hw4.feature @@ -2,9 +2,9 @@ Feature: Update Target search test cases and add Behave variables ##Open Target Circle and verify 10 benefit cells - Scenario: User can open Target Circle with 10 benefit cells + Scenario: User can open Target Circle with 2 storycards Given Open Target circle page - Then Verify 10 or more benefit cells + Then Verify two storycards ## Add a Target product to cart And Verify it is there diff --git a/features/tests/target_search_hw5.feature b/features/tests/target_search_hw5.feature index f9b4fae40..a1f8680e7 100644 --- a/features/tests/target_search_hw5.feature +++ b/features/tests/target_search_hw5.feature @@ -3,5 +3,5 @@ Feature: Update Target search test cases and add Behave variables ##Search for color of product, click each color, verify color selected Scenario: Add product to cart - Given Open target product {x-ray-men-s-cable-knit-cowl-neck-sweater/-/A-1001689658} page + Given Open target product {men-s-soft-knit-johnny-collar-polo-sweater-goodfellow-co/-/A-94329580?preselect=94405482#lnk=sametab} page Then Click through colors and verify selection diff --git a/features/tests/target_search_hw6.feature b/features/tests/target_search_hw6.feature new file mode 100644 index 000000000..896089414 --- /dev/null +++ b/features/tests/target_search_hw6.feature @@ -0,0 +1,7 @@ +Feature: Update target Page Object + + +Scenario: "Your cart is empty" message is shown for empty cart + Given Open target.com + When Click on Cart icon + Then Verify 'Your cart is empty' message is shown \ 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..3b0109e2e --- /dev/null +++ b/pages/base_page.py @@ -0,0 +1,19 @@ +class Page: + + def __init__(self, driver): + self.driver = driver + + def open_url(self, 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): + self.driver.find_element(*locator).send_keys(text) \ No newline at end of file diff --git a/pages/cart_page.py b/pages/cart_page.py new file mode 100644 index 000000000..c9324a444 --- /dev/null +++ b/pages/cart_page.py @@ -0,0 +1,11 @@ +from selenium.webdriver.common.by import By +from pages.base_page import Page + +class CartPage(Page): + def open_cart(self): + self.open_url('https://www.target.com/cart') + + def verify_empty_cart(self): + expected_result = 'Your cart is empty' + actual_result = self.find_element(By.CSS_SELECTOR, "[data-test='boxEmptyMsg']").text + assert expected_result == actual_result, f'Expected {expected_result} did not match actual {actual_result}' diff --git a/pages/header.py b/pages/header.py new file mode 100644 index 000000000..54d2b03c3 --- /dev/null +++ b/pages/header.py @@ -0,0 +1,16 @@ +from selenium.webdriver.common.by import By +from pages.base_page import Page + + +class Header(Page): + SEARCH_FIELD = (By.ID, 'search') + SEARCH_BTN = (By.XPATH, "//button[@data-test='@web/Search/SearchButton']") + CART_ICON = (By.CSS_SELECTOR, '[data-test="@web/CartLink"]') + + def search(self, text): + print(f'Searching for {text}') + self.input_text(text, *self.SEARCH_FIELD) + self.click(*self.SEARCH_BTN) + + def click_cart_icon(self): + self.click(*self.CART_ICON) \ No newline at end of file diff --git a/pages/main_page.py b/pages/main_page.py new file mode 100644 index 000000000..40712ff8e --- /dev/null +++ b/pages/main_page.py @@ -0,0 +1,6 @@ +from pages.base_page import Page + +class MainPage(Page): + + def open_main_page(self): + self.open_url('https://www.target.com/') diff --git a/pages/search_results_page.py b/pages/search_results_page.py new file mode 100644 index 000000000..f35e29589 --- /dev/null +++ b/pages/search_results_page.py @@ -0,0 +1,11 @@ +from selenium.webdriver.common.by import By + +from pages.base_page import Page + + +class SearchResultsPage(Page): + SEARCH_RESULTS_TEXT = (By.XPATH, "//div[@data-test='lp-resultsCount']") + + def verify_search_results(self, expected_text): + actual_text = self.find_element(*self.SEARCH_RESULTS_TEXT).text + assert expected_text in actual_text, f'Error. Text {expected_text} not in {actual_text}' \ No newline at end of file From bd574cea0f565dcb0a49e94e566a617d4dcd61d7 Mon Sep 17 00:00:00 2001 From: Justin Pauge Date: Sun, 8 Feb 2026 23:12:28 -0800 Subject: [PATCH 4/4] final commit for hw --- features/steps/target_search_steps_hw5.py | 2 +- features/tests/target_search_hw4.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/steps/target_search_steps_hw5.py b/features/steps/target_search_steps_hw5.py index 6dee3018d..87f6f3999 100644 --- a/features/steps/target_search_steps_hw5.py +++ b/features/steps/target_search_steps_hw5.py @@ -31,7 +31,7 @@ def verify_color(context): for color in colors[0:3]: sleep(5) color.click() - selected_color = context.driver.find_element(*SELECTED_COLOR).text[1] # 'Color\nBlack' + selected_color = context.driver.find_element(*SELECTED_COLOR).text[6:] # 'Color\nBlack' print('Current color', selected_color) #selected_color = selected_color.split('color\n39063-')[1] # remove 'Color\n' part, keep Black' sleep(3) diff --git a/features/tests/target_search_hw4.feature b/features/tests/target_search_hw4.feature index a11964f85..bd79830bb 100644 --- a/features/tests/target_search_hw4.feature +++ b/features/tests/target_search_hw4.feature @@ -1,7 +1,7 @@ Feature: Update Target search test cases and add Behave variables -##Open Target Circle and verify 10 benefit cells +##Open Target Circle and verify 2 storycards Scenario: User can open Target Circle with 2 storycards Given Open Target circle page Then Verify two storycards