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/features/css_selectors_hw3.py b/features/css_selectors_hw3.py new file mode 100644 index 000000000..fe69104cd --- /dev/null +++ b/features/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/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 new file mode 100644 index 000000000..7775da806 --- /dev/null +++ b/features/locators_hw2.py @@ -0,0 +1,77 @@ +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/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') + +sleep(10) + +####LOCATORS +#Amazon Logo +driver.find_element(By.CSS_SELECTOR, '[class="a-icon a-icon-logo"]') + +#Email field +driver.find_element(By.CSS_SELECTOR,'[class="a-input-text"]') + +#Continue button +driver.find_element(By.CSS_SELECTOR, '[class="a-button-input"]') + +#Conditions of use link +driver.find_element(By.CSS_SELECTOR, 'a[href*="/gp/help/customer/display.html/ref=ap_signin_notification_condition_of_use"]') + +#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/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..0c4b067d6 --- /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..57485afb2 --- /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="sc-3e90527f-1 colamC storycard--text"') +ADD_CART_BUTTON = (By.CSS_SELECTOR, '[id*="addToCartButtonOrTextIdFor"]') +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']") + + +@given('Open Target circle page') +def open_cart(context): + context.driver.get('https://www.target.com/circle') + sleep(3) + + +@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(10) + context.driver.find_element(*ADD_CART_BUTTON_2).click() + sleep(5) + 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..87f6f3999 --- /dev/null +++ b/features/steps/target_search_steps_hw5.py @@ -0,0 +1,41 @@ + +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[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): +# 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(5) + expected_colors = ['Berry Pink', 'Charcoal Gray', 'Light Beige'] + actual_colors = [] + colors = context.driver.find_elements(*COLOR_OPTIONS) + print(len(colors)) + for color in colors[0:3]: + sleep(5) + color.click() + 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) + 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..bd79830bb --- /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 2 storycards + Scenario: User can open Target Circle with 2 storycards + Given Open Target circle page + Then Verify two storycards + + +## 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..a1f8680e7 --- /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 {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/file.txt b/file.txt new file mode 100644 index 000000000..e69de29bb 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