diff --git a/features/steps/__init__.py b/Application/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from features/steps/__init__.py rename to Application/__init__.py diff --git a/Application/application.py b/Application/application.py new file mode 100644 index 00000000..671280da --- /dev/null +++ b/Application/application.py @@ -0,0 +1,35 @@ +from Pages.base_page import BasePage +from Pages.Main_page import MainPage +from Pages.header import HeaderPage +from Pages.cart_messages import Cart +from Pages.search_results_page import SearchResultsPage +from Pages.chips_page import ChipsPage +from Pages.sign_in import SignPage +from Pages.terms_conditions_page import TermsConditionsPage +from Pages.target_help_page import TargetHelpPage + + + + +class Application: + def __init__(self, driver): + self.driver = driver + self.base_page=BasePage(driver) + self.Main_page=MainPage(driver) + self.header_page=HeaderPage(driver) + self.search_results_page=SearchResultsPage(driver) + self.cart_messages=Cart(driver) + self.chips_page = ChipsPage(driver) + self.sign_in=SignPage(driver) + self.terms_conditions_page=TermsConditionsPage(driver) + self.target_help_page=TargetHelpPage(driver) + + + + + + + + + + diff --git a/Pages/Main_page.py b/Pages/Main_page.py new file mode 100644 index 00000000..aa108b93 --- /dev/null +++ b/Pages/Main_page.py @@ -0,0 +1,8 @@ +from Pages.base_page import BasePage + +class MainPage(BasePage): + + def open_main_page(self): + self.open_url('www.target.com') + + diff --git a/features/tests/__init__.py b/Pages/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from features/tests/__init__.py rename to Pages/__init__.py diff --git a/Pages/base_page.py b/Pages/base_page.py new file mode 100644 index 00000000..d22f04d5 --- /dev/null +++ b/Pages/base_page.py @@ -0,0 +1,86 @@ +from selenium.webdriver.support.select import Select +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + + +class BasePage: + + def __init__(self, driver): + self.driver = driver + self.wait = WebDriverWait(driver, 15) + + def open_url(self,url): + self.driver.get(url) + + def get_url(self): + return self.driver.current_url() + + def click(self,*locator): + self.driver.find_element(*locator).click() + + def find_element(self,*locator): + return self.driver.find_element(*locator) + + def input_text(self,text,*locator): + self.driver.find_element(*locator).send_keys(text) + + def get_current_window_handle(self): + return self.driver.current_window_handle() + + def switch_to_new_window(self): + self.wait.until(EC.new_window_is_opened()) + all_windows = self.driver.window_handles + print('All windows: ', all_windows) + self.driver.switch_to.window(all_windows[1]) + print('Current window: ', self.driver.current_window_handle) + + def switch_to_original_window(self,window_id): + self.driver.switch_to.window(window_id) + print("Current Window: ", self.driver.current_window_handle) + + def select_topic(self, option_value): + dd = self.find_element(*self.option_value) + select = Select(dd) + select.select_by_value(option_value) + + + def wait_for_element_visible(self, locator): + return self.wait.until(EC.visibility_of_element_located(locator), + message=f'Element by {locator} not visible') + + def wait_for_element_invisible(self, locator): + self.wait.until( + EC.invisibility_of_element_located(locator), + message=f'Element by {locator} should not be visible' + ) + + def wait_for_element_clickable(self, locator): + return self.wait.until( + EC.element_to_be_clickable(locator), + message=f'Element by {locator} not clickable' + ) + + def wait_and_click(self,locator): + self.wait.until( + EC.element_to_be_clickable(locator), + message=f'Element by {locator} not clickable' + ).click() + + def verify_partial_text(self, expected_text, *locator): + actual_text = self.find_element(*locator).text + assert expected_text in actual_text, f'Expected {expected_text} not in actual {actual_text}' + + def verify_text(self, expected_text, *locator): + actual_text = self.find_element(*locator).text + assert expected_text == actual_text, f'Expected {expected_text}, but got {actual_text}' + + def verify_partial_url(self, expected_url): + actual_url = self.driver.current_url + assert expected_url in actual_url, f'Expected partial url {expected_url} not in actual {actual_url}' + + def verify_url(self, expected_url): + actual_url = self.driver.current_url + assert expected_url == actual_url, f'Expected url {expected_url} does not match actual {actual_url}' + + def close(self): + self.driver.close() diff --git a/Pages/cart_messages.py b/Pages/cart_messages.py new file mode 100644 index 00000000..ca81945d --- /dev/null +++ b/Pages/cart_messages.py @@ -0,0 +1,24 @@ +from selenium.webdriver.common.by import By +from time import sleep +from Pages.base_page import BasePage + +class Cart(BasePage): + CART_ICON = By.CSS_SELECTOR,"div[data-test='@web/CartIcon']" + MESSAGE = By.CSS_SELECTOR,"div[data-test='boxEmptyMsg']" + PRODUCT_IN_CART = By.XPATH, "//span[text()='$6.69 subtotal']" + + def click_cart(self,*locator): + self.click(*self.CART_ICON) + sleep(5) + + def verify_message(self,*locator): + self.find_element(*self.MESSAGE) + + def product_in_cart(self,*locator): + self.find_element(*self.PRODUCT_IN_CART) + + + + + + diff --git a/Pages/chips_page.py b/Pages/chips_page.py new file mode 100644 index 00000000..b9f590c9 --- /dev/null +++ b/Pages/chips_page.py @@ -0,0 +1,10 @@ +from Pages.base_page import BasePage +from selenium.webdriver.common.by import By +from time import sleep + +class ChipsPage(BasePage): + + ADD_TO_CART_ON_CHIPS_PAGE = By.CSS_SELECTOR, "[aria-label='Add Doritos Nacho Cheese Flavor Party Size Tortilla Chips - 14.5oz to cart']" + +def click_add_to_cart(self ,*locator): + self.click(*self.ADD_TO_CART_ON_CHIPS_PAGE) \ No newline at end of file diff --git a/Pages/header.py b/Pages/header.py new file mode 100644 index 00000000..e3fb8da0 --- /dev/null +++ b/Pages/header.py @@ -0,0 +1,67 @@ +from selenium.webdriver import Keys + +from Pages.base_page import BasePage +from selenium.webdriver.common.by import By +from time import sleep + +class HeaderPage(BasePage): + + SEARCH_BAR=By.CSS_SELECTOR, "[data-test='@web/Search/SearchInput']" + SEARCH_BTN=By.CSS_SELECTOR, "[data-test='@web/Search/SearchButton']" + SIGN_IN_BUTTON = By.CSS_SELECTOR,"[aria-label='Account, sign in']" + SIDE_NAV_SIGN_IN = By.CSS_SELECTOR,"[data-test='accountNav-signIn']" + SIGN_IN_MESSAGE = By.CSS_SELECTOR, "//span[text()='Sign into your Target account']" + CATEGORIES_BTN =By.CSS_SELECTOR,"[aria-label='Categories']" + GROCERY_BTN = By.CSS_SELECTOR,"[data-url='/c/grocery/-/N-5xt1a']" + SNACK_BTN = By.CSS_SELECTOR,"[data-url='/c/snacks-grocery/-/N-5xsy9']" + CHIPS_BTN = By.CSS_SELECTOR, "[data-url='/c/chips-snacks-grocery/-/N-5xsy7']" + ADD_TO_CART_SIDE_NAV_PAGE = By.CSS_SELECTOR, "[data-test='orderPickupButton']" + VIEW_CART = By.CSS_SELECTOR, "[href='/cart']" + + def click_category(self,*locator): + self.click(*self.CATEGORIES_BTN) + + + def click_grocery(self,*locator): + self.click(*self.GROCERY_BTN) + + + def click_snacks(self,*locator): + self.click(*self.SNACK_BTN) + + + def click_chips(self,*locator): + self.click(*self.CHIPS_BTN) + + + def click_add_to_side(self,*locator): + self.click(*self.ADD_TO_CART_SIDE_NAV_PAGE) + + + def click_view_cart(self,*locator): + self.click(*self.VIEW_CART) + + + def search_bar(self,product,*locator): + self.input_text(product,*self.SEARCH_BAR).send_keys(product) + self.click(*self.SEARCH_BTN) + sleep(10) + + + def sign_in(self,*locator): + self.click(*self.SIGN_IN_BUTTON) + sleep(5) + + + def side_nav_sign_in(self,*locator): + self.click(*self.SIDE_NAV_SIGN_IN) + sleep(5) + + + def verify_sign_in_page(self,expected_text,*locator): + self.verify_text('Sign into your Target account',*self.SIGN_IN_MESSAGE) + + + + + diff --git a/Pages/help_page.py b/Pages/help_page.py new file mode 100644 index 00000000..84c8e7d9 --- /dev/null +++ b/Pages/help_page.py @@ -0,0 +1,36 @@ +from selenium.webdriver.common.by import By +from Pages.base_page import BasePage + + +# #class HelpPage(BasePage): +# TOPIC_SELECTION_DD = (By.CSS_SELECTOR, "select[id*='ViewHelpTopics']") +# HEADER = (By.XPATH, "//h1[text()=' {SUBSTRING}']") +# +# def _get_header_locator(self, header): +# # HEADER (By.XPATH, "//h1[text()=' {SUBSTRING}']") => (By.XPATH, "//h1[text()=' Returns']") +# return [self.HEADER[0], self.HEADER[1].replace('{SUBSTRING}', header)] +# +# +# def open_help_page(self): +# self.open_url("https://help.target.com/help/SubCategoryArticle?childcat=Returns&parentcat=Returns+%26+Exchanges") +# +# +# def choose_topic(self): +# self.select_topic(*self.TOPIC_SELECTION_DD) +# +# +# def verify_target_help_page_opened(self): +# self.verify_url("https://help.target.com/help/SubCategoryArticle?childcat=Returns&parentcat=Returns+%26+Exchanges") +# +# +# def verify_topic_page_opened(self,header): +# locator = self._get_header_locator(header) +# print(locator) +# self.wait_for_element_visible(locator) + + + + + + + diff --git a/Pages/search_results_page.py b/Pages/search_results_page.py new file mode 100644 index 00000000..5ebb9dc6 --- /dev/null +++ b/Pages/search_results_page.py @@ -0,0 +1,9 @@ +from selenium.webdriver.common.by import By +from Pages.base_page import BasePage + +class SearchResultsPage(BasePage): + SEARCH_RESULT=By.CSS_SELECTOR, "[data-test='resultsHeading']" + + def verify_search_results(self,product): + actual_result = self.find_element(*self.SEARCH_RESULT).text + assert product in actual_result, f'Expected result {product} not in {actual_result}' \ No newline at end of file diff --git a/Pages/sign_in.py b/Pages/sign_in.py new file mode 100644 index 00000000..d01d5ffa --- /dev/null +++ b/Pages/sign_in.py @@ -0,0 +1,42 @@ +from Pages.base_page import BasePage +from selenium.webdriver.common.by import By +from time import sleep + + +class SignPage(BasePage): + Terms_conditions = (By.XPATH,"//a[contains(text(),'Terms')]") + EMAIL = (By.CSS_SELECTOR, "#username") + CONTINUE = (By.CSS_SELECTOR, "#login" ) + PASSWORD = (By.CSS_SELECTOR, "#password") + SIGN_IN = (By.CSS_SELECTOR, "#login") + ERROR = (By.CSS_SELECTOR, "#password--ErrorMessage") + + + def open_sign_in(self): + self.open_url('https://www.target.com/login?client_id=ecom-web-1.0.0&ui_namespace=ui-default&back_button_action=browser&keep_me_signed_in=true&kmsi_default=false&actions=create_session_request_username') + + def enter_email(self): + self.input_text("katie@gmail.com ",*self.EMAIL) + + def click_continue(self): + self.click(*self.CONTINUE) + + def enter_password(self): + self.input_text("password",*self.PASSWORD) + + def click_sign_in(self): + self.click(*self.SIGN_IN) + + def click_terms(self): + self.click(self.Terms_conditions) + + def verify_terms_opened(self): + self.verify_partial_url('terms-conditions') + + def verify_error_message(self): + self.verify_text("Please enter a valid password",*self.ERROR) + + + + + diff --git a/Pages/target_help_page.py b/Pages/target_help_page.py new file mode 100644 index 00000000..bd9c9571 --- /dev/null +++ b/Pages/target_help_page.py @@ -0,0 +1,29 @@ +from Pages.base_page import BasePage +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select +from time import sleep + +class TargetHelpPage(BasePage): + DD = (By.CSS_SELECTOR, "[name='j_id0:contentTemplate:j_id79:j_id80:viewHelpTopics:ViewHelpTopics']") + + def open_target_help_page(self): + self.open_url("https://help.target.com/help/SubCategoryArticle?childcat=Returns&parentcat=Returns+%26+Exchanges") + sleep(5) + + def verify_help_page_opened(self): + self.verify_url("https://help.target.com/help/SubCategoryArticle?childcat=Returns&parentcat=Returns+%26+Exchanges") + + def select_topic_target_help_page(self): + dropdown = self.find_element(*self.DD) + select = Select(dropdown) + select.select_by_value('Orders & Purchases') + sleep(5) + + def verify_orders_and_purchases_opened(self): + self.verify_url("https://help.target.com/help/SubCategoryArticle?childcat=Print+a+receipt&parentcat=Orders+%26+Purchases&searchQuery=") + + + + + + diff --git a/Pages/terms_conditions_page.py b/Pages/terms_conditions_page.py new file mode 100644 index 00000000..c0c0d3e4 --- /dev/null +++ b/Pages/terms_conditions_page.py @@ -0,0 +1,10 @@ +from Pages.base_page import BasePage +from selenium.webdriver.common.by import By +from time import sleep + +class TermsConditionsPage(BasePage): + + def verify_terms(self): + self.verify_partial_text('terms-conditions') + + diff --git a/README.md b/README.md index 581349c3..dfde9609 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ written in ### Python 3, Behave https://www.careerist.com/automation + +poop diff --git a/features/environment.py b/features/environment.py index 1275460a..bf41b2b1 100755 --- a/features/environment.py +++ b/features/environment.py @@ -1,24 +1,48 @@ from selenium import webdriver from selenium.webdriver.chrome.service import Service +from selenium.webdriver.support.wait import WebDriverWait from webdriver_manager.chrome import ChromeDriverManager +from Application.application import Application +from webdriver_manager.firefox import GeckoDriverManager +from selenium.webdriver.chrome.options import Options -def browser_init(context): +def browser_init(context, scenario_name): """ + :param scenario_name: :param context: Behave context """ driver_path = ChromeDriverManager().install() service = Service(driver_path) context.driver = webdriver.Chrome(service=service) - context.driver.maximize_window() - context.driver.implicitly_wait(4) + + # ### BROWSERSTACK ### + # # Register for BrowserStack, then grab it from https://www.browserstack.com/accounts/settings + # bs_user = 'poojap_n58Du0' + # bs_key = 'jFHNdxSxEVo9CJ5NkVsV' + # url = f'http://{bs_user}:{bs_key}@hub-cloud.browserstack.com/wd/hub' + # + # options = Options() + # bstack_options = { + # "os": "Windows", + # "osVersion": "11", + # 'browserName': 'edge', + # 'sessionName': scenario_name, + # } + # options.set_capability('bstack:options', bstack_options) + # context.driver = webdriver.Remote(command_executor=url, options=options) + + context.driver.maximize_window() + context.driver.wait = WebDriverWait(context.driver, 15) + context.app = Application(context.driver) + #context.driver.implicitly_wait(5) + def before_scenario(context, scenario): print('\nStarted scenario: ', scenario.name) - browser_init(context) - + browser_init(context, scenario.name) def before_step(context, step): print('\nStarted step: ', step) diff --git a/features/steps/add product to cart steps.py b/features/steps/add product to cart steps.py new file mode 100644 index 00000000..79dddce4 --- /dev/null +++ b/features/steps/add product to cart steps.py @@ -0,0 +1,34 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + +@when("Click on Grocery") +def click_grocery(context): + context.app.header.click_grocery() + + +@when("Click on Snacks") +def click_snacks(context): + context.app.header.click_snacks() + + +@when("Click on Chips") +def click_chips(context): + context.app.header.click_chips() + + +@when("Click on Add to cart for Doritos") +def click_add_to_cart(context): + context.app.chips_page.click_add_to_cart() + + +@when("Click on Add to cart side nav") +def click_add_to_cart_side_nav(context): + context.app.header.click_add_to_side() + + +@then("Verify if {product} is shown") +def verify_product(context,product): + context.app.cart_messages.product_in_cart(product) + + diff --git a/features/steps/cart_empty.py b/features/steps/cart_empty.py new file mode 100644 index 00000000..3c283eb4 --- /dev/null +++ b/features/steps/cart_empty.py @@ -0,0 +1,16 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + +@when("Click on Cart icon") +def click_cart_icon(context): + context.app.cart_empty.click_cart.click() + + +@then("Verify “Your cart is empty” message is shown") +def verify_cart_empty(context): + expected_text = "Your cart is empty" + actual_result = context.driver.find_element(By.CSS_SELECTOR,"div[data-test='boxEmptyMsg']").text + assert expected_text in actual_result,f'{expected_text} not in {actual_result}' + context.app.cart_empty.verify_message(actual_result) diff --git a/features/steps/product colors steps.py b/features/steps/product colors steps.py new file mode 100644 index 00000000..b2ab5e09 --- /dev/null +++ b/features/steps/product colors steps.py @@ -0,0 +1,38 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + + +@given("a specific product") +def product_page(context): + context.driver.get("https://www.target.com/p/A-54551690") +sleep (3) + + +@then("Verify if product with specific color is displayed") +def verify_product_color(context): + product_color = ["Blue Tint", "Denim Blue", "Raven", "Marine"] + actual_colors = [] + + colors = context.driver.find_elements(By.CSS_SELECTOR,"div[aria-label='Carousel']") + + for color in colors: + color.click() + + selected_colors= context.driver.find_element(By.CSS_SELECTOR,"[data-test='@web/VariationComponent'] div") + print('Current color',selected_colors) + + selected_color = selected_color.split('\n')[1] # remove 'Color\n' part, keep Black' + actual_colors.append(selected_color) + print(actual_colors) + + assert selected_color == actual_colors, f'Expected {selected_color} did not match actual {actual_colors}' + + + + + + + + diff --git a/features/steps/product page target.py b/features/steps/product page target.py new file mode 100644 index 00000000..17dd62b1 --- /dev/null +++ b/features/steps/product page target.py @@ -0,0 +1,33 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + + +LISTINGS = (By.CSS_SELECTOR, "[data-test*='@web/site-top-of-funnel/ProductCardWrapper']") +PRODUCT_TITLE = (By.CSS_SELECTOR, "[data-test='product-title']") +PRODUCT_IMG = (By.CSS_SELECTOR, 'img') + +@given('Open Target product page') +def open_product_page(context): + context.driver.get('https://www.target.com/c/laundry-care-household-essentials/all-deals/-/N-5xsyrZakkos') + sleep(4) + + +@then('Verify that every product has a name and an image') +def verify_products_name_img(context): + # To see ALL listings (comment out if you only check top ones): + context.driver.execute_script("window.scrollBy(0,2000)", "") + sleep(4) + context.driver.execute_script("window.scrollBy(0,2000)", "") + + # Find all products: + all_products = context.driver.find_elements(*LISTINGS) + # print(all_products) + assert len(all_products) > 0, 'No products found' + + for product in all_products: + title = product.find_element(*PRODUCT_TITLE).text + assert title, 'Product title not shown' + print(title) + product.find_element(*PRODUCT_IMG) diff --git a/features/steps/product_search.py b/features/steps/product_search.py deleted file mode 100755 index 4e142cb4..00000000 --- a/features/steps/product_search.py +++ /dev/null @@ -1,32 +0,0 @@ -from selenium.webdriver.common.by import By -from behave import given, when, then -from time import sleep - - -SEARCH_INPUT = (By.NAME, 'q') -SEARCH_SUBMIT = (By.NAME, 'btnK') - - -@given('Open Google page') -def open_google(context): - context.driver.get('https://www.google.com/') - - -@when('Input {search_word} into search field') -def input_search(context, search_word): - search = context.driver.find_element(*SEARCH_INPUT) - search.clear() - search.send_keys(search_word) - sleep(4) - - -@when('Click on search icon') -def click_search_icon(context): - context.driver.find_element(*SEARCH_SUBMIT).click() - sleep(1) - - -@then('Product results for {search_word} are shown') -def verify_found_results_text(context, search_word): - assert search_word.lower() in context.driver.current_url.lower(), \ - f'Expected query not in {context.driver.current_url.lower()}' diff --git a/features/steps/sign in steps.py b/features/steps/sign in steps.py new file mode 100644 index 00000000..72548f6b --- /dev/null +++ b/features/steps/sign in steps.py @@ -0,0 +1,68 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then + + +@given('Open sign in page') +def open_sign_in_page(context): + context.app.sign_in.open_sign_in() + + +@when('Store original window') +def store_original_window(context): + context.original_window= context.app.sign_in.get_current_window_handle() + + +@when('Click on Target terms and conditions link') +def click_target_terms_and_conditions(context): + context.app.sign_in.click_terms() + + +@when('Switch to the newly opened window') +def switch_to_newly_opened_window(context): + context.app.sign_in.switch_to.window(context.driver.window_handle[1]) + + +@when("user inputs correct email address") +def enter_email(context): + context.app.sign_in.enter_email() + + +@when("User clicks continue button") +def continue_button(context): + context.app.sign_in.click_continue() + + +@when("user enters incorrect password") +def enter_password(context): + context.app.sign_in.enter_password() + + +@when("Clicks sign in with password") +def clicks_sign_in_password(context): + context.app.sign_in.click_sign_in() + + + +@then('Verify Terms and Conditions page is opened') +def verify_terms_and_conditions_page(context): + context.app.terms_conditions_page.verify_terms() + + +@then('User can close new window') +def user_close_new_window(context): + context.app.terms_conditions_page.close() + + +@then('switch back to original') +def switch_to_original_window(context): + context.app.sign_in.switch_to_original_window(context.original_window) + + +@then("Verify error message is shown") +def verify_error_message(context): + context.app.sign_in.verify_error_message() + + + + + diff --git a/features/steps/sign into account.py b/features/steps/sign into account.py new file mode 100644 index 00000000..4e4d1f0a --- /dev/null +++ b/features/steps/sign into account.py @@ -0,0 +1,15 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then + + +@when('user clicks on sign in button') +def sign_in(context): + context.app.header.sign_in() + +@when('user clicks on side navigation side in button') +def side_navigation(context): + context.app.header.side_nav_sign_in() + +@then('Verify if Sign in message is displayed') +def verify_sign_in(context): + context.app.header.verify_sign_in_page() \ No newline at end of file diff --git a/features/steps/target cart steps.py b/features/steps/target cart steps.py new file mode 100644 index 00000000..aeea828b --- /dev/null +++ b/features/steps/target cart steps.py @@ -0,0 +1,68 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from selenium.webdriver.support import expected_conditions as EC +from selenium import webdriver +driver = webdriver.Chrome() +driver.implicitly_wait(5) + + +CLICK_CATEGORIES = By.CSS_SELECTOR, "[aria-label='Categories']" +CLICK_CHRISTMAS = By.CSS_SELECTOR, "[data-url='/c/christmas/-/N-5xt30']" +CLICK_DEALS = By.CSS_SELECTOR,"[data-url='/c/christmas-deals/-/N-4rr05']" +CLICK_TREES = By.CSS_SELECTOR,"[src='https://target.scene7.com/is/image/Target/GUEST_5ea06363-e13a-4069-8469-cd7cbf892955?wid=315&hei=315&qlt=60&fmt=webp']" +FIRST_TREE = By.CSS_SELECTOR,"[data-test='@web/ProductCard/body']" +ADD_TO_CART = By.CSS_SELECTOR,"[aria-label*='Artificial Christmas Tree Holiday Decor with 450']" +VIEW_CART = By.CSS_SELECTOR,"[href='/cart']" + + + + +@when('Click on Categories') +def click_categories(context): + context.driver.wait.until(EC.element_to_be_clickable(CLICK_CATEGORIES)).click() + + +@when('Click on Christmas button') +def click_christmas(context): + context.driver.find_element(*CLICK_CHRISTMAS).click() + + + +@when('Click on Christmas Deals') +def click_christmas_deals(context): + context.driver.find_element(*CLICK_DEALS).click() + + + +@when('Click on Christmas Trees') +def click_christmas_trees(context): + context.driver.find_element(*CLICK_TREES).click() + + + +@when('Click on first christmas tree') +def click_first_tree(context): + context.driver.find_element(*FIRST_TREE).click() + + + +@when('Click on Add to cart') +def click_add_to_cart(context): + context.driver.wait.until(EC.element_to_be_clickable(ADD_TO_CART)).click() + + +@when('Click on view cart and checkout button') +def view_cart(context): + context.driver.find_element(*VIEW_CART).click() + + +@then('Verify if result is shown') +def verify_result(context): + expected_value = "$234.99 subtotal 1 item" + actual_result= context.driver.find_element(By.CSS_SELECTOR,"#cart-summary-heading").click() + assert expected_value == actual_result,f'{expected_value} != {actual_result}' + print(actual_result) + + + + diff --git a/features/steps/target circle steps.py b/features/steps/target circle steps.py new file mode 100644 index 00000000..cd776c13 --- /dev/null +++ b/features/steps/target circle steps.py @@ -0,0 +1,19 @@ +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 + + + +@when('Click on Target Circle button') +def search_circle(context): + context.driver.wait.until(EC.element_to_be_clickable(*SEARCH_CIRCLE)).click() + + +@then('Verify at least 10 cells present') +def results_for_circle(context): + actual_results_circle = context.driver.find_elements(*RESULTS) + print(actual_results_circle) + + assert len(actual_results_circle) >= 10,f'Expected 10 links, but got {len(actual_results_circle)}' + sleep(3) \ No newline at end of file diff --git a/features/steps/target search.py b/features/steps/target search.py new file mode 100644 index 00000000..fc456c5e --- /dev/null +++ b/features/steps/target search.py @@ -0,0 +1,32 @@ +from selenium.webdriver.common.by import By +from behave import given, when, then +from time import sleep + + +@given('Open Target page') +def open_target(context): + context.app.Main_page.open_main_page() + sleep(3) + + +@when('search for a {product}') +def search_product(context, product): + context.driver.find_element(By.CSS_SELECTOR, "[data-test='@web/Search/SearchInput']").send_keys(product) + context.driver.find_element(By.CSS_SELECTOR, "[data-test='@web/Search/SearchButton']").click() + sleep(10) + context.app.header.search_bar(product) + + +@then('verify search for results are shown for {product}') +def results_for_product(context,product): + actual_result = context.driver.find_element(By.CSS_SELECTOR, "[data-test='resultsHeading']").text + assert product in actual_result,f'Expected result {product} not in {actual_result}' + sleep(3) + context.app.search_results_page.verify_search_results(product) + + + + + + + diff --git a/features/steps/target_help_steps.py b/features/steps/target_help_steps.py new file mode 100644 index 00000000..96cb95c9 --- /dev/null +++ b/features/steps/target_help_steps.py @@ -0,0 +1,24 @@ +from behave import given, when, then + + + +@given("Open Target Help Page") +def open_help_page(context): + context.app.target_help_page.open_target_help_page() + + +@then("Verify Target Help Page Opened") +def verify_target_help_page_opened(context): + context.app.target_help_page.verify_help_page_opened() + + +@then("Select Target topic Orders and Purchases") +def select_target_topic_orders_and_purchases(context): + context.app.target_help_page.select_topic_target_help_page() + + +@then("Verify Orders and Purchases page opened") +def verify_orders_and_purchases(context): + context.app.target_help_pageverify_orders_and_purchases_opened() + + diff --git a/features/tests/Add products to cart .feature b/features/tests/Add products to cart .feature new file mode 100644 index 00000000..71385977 --- /dev/null +++ b/features/tests/Add products to cart .feature @@ -0,0 +1,13 @@ + +Feature: Adding a product to cart + + Scenario: User will be able to add a product into their cart + Given Open Target page + When Click on Categories + When Click on Grocery + When Click on Snacks + When Click on Chips + When Click on Add to cart for Doritos + When Click on Add to cart side nav + When Click on view cart and checkout button + Then Verify if {product} is shown diff --git a/features/tests/Product colors .feature b/features/tests/Product colors .feature new file mode 100644 index 00000000..b5239f7f --- /dev/null +++ b/features/tests/Product colors .feature @@ -0,0 +1,7 @@ + +Feature: Searching for different colors of a product + + + Scenario: Use can click on different colors of a product + Given a specific product + Then Verify if product with specific color is displayed diff --git a/features/tests/airpods example .feature b/features/tests/airpods example .feature new file mode 100644 index 00000000..82ac2dbb --- /dev/null +++ b/features/tests/airpods example .feature @@ -0,0 +1,6 @@ + +Feature: Target product page + + Scenario: Verify that user can see product names and images + Given Open target product page + Then Verify that every product has a name and an image \ No newline at end of file diff --git a/features/tests/cart_empty.feature b/features/tests/cart_empty.feature new file mode 100644 index 00000000..0b51e644 --- /dev/null +++ b/features/tests/cart_empty.feature @@ -0,0 +1,6 @@ +Feature: Cart Empty + +Scenario: “Your cart is empty” message is shown for empty cart + Given Open Target page + When Click on Cart icon + Then Verify “Your cart is empty” message is shown diff --git a/features/tests/product_search.feature b/features/tests/product_search.feature deleted file mode 100755 index 36d6913c..00000000 --- a/features/tests/product_search.feature +++ /dev/null @@ -1,7 +0,0 @@ -Feature: Test Scenarios for Search functionality - - Scenario: User can search for a product - Given Open Google page - When Input Car into search field - And Click on search icon - Then Product results for Car are shown \ 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 00000000..809a906d --- /dev/null +++ b/features/tests/sign in .feature @@ -0,0 +1,20 @@ + +Feature: Sign In + + Scenario: User can sign into target account + Given Target main page + When user clicks on sign in button + When user clicks on side navigation side in button + Then Verify if Sign in message is displayed + +Scenario: User cannot sign in with incorrect password + Given Open Target page + When user clicks on sign in button + And user clicks on side navigation side in button + And user inputs correct email address + And User clicks continue button + When user enters incorrect password + And Clicks sign in with password + Then Verify error message is shown + + diff --git a/features/tests/target cart search .feature b/features/tests/target cart search .feature new file mode 100644 index 00000000..0f5b9c13 --- /dev/null +++ b/features/tests/target cart search .feature @@ -0,0 +1,15 @@ + +Feature: Adding products to Target cart + + + Scenario: User can add a product into target cart + Given Open Target page + When Click on Categories + When Click on Christmas button + When Click on Christmas Deals + When Click on Christmas Trees + When Click on first christmas tree + When Click on Add to cart + When Click on view cart and checkout button + Then Verify if result is shown + diff --git a/features/tests/target circle page.feature b/features/tests/target circle page.feature new file mode 100644 index 00000000..9a950e30 --- /dev/null +++ b/features/tests/target circle page.feature @@ -0,0 +1,9 @@ + +Feature: User can see 10 cells when on Target circle page + + + Scenario: + Given Open Target page + When Click on Target Circle button + Then Verify at least 10 cells present + diff --git a/features/tests/target search.feature b/features/tests/target search.feature new file mode 100644 index 00000000..60a73130 --- /dev/null +++ b/features/tests/target search.feature @@ -0,0 +1,13 @@ +Feature: Target search page + + Scenario Outline: User can search for a product + Given Open Target page + When search for a + Then verify search for results are shown for + Examples: + | product | + | coffee | + | mug | + | tea | + + diff --git a/features/tests/target_help.feature b/features/tests/target_help.feature new file mode 100644 index 00000000..815a5361 --- /dev/null +++ b/features/tests/target_help.feature @@ -0,0 +1,10 @@ + +Feature: Dropdown menu on Target Help page + + Scenario: User can select different topics on Target Help Page + Given Open Target Help Page + Then Verify Target Help Page Opened + Then Select Target topic Orders and Purchases + Then Verify Orders and Purchases page opened + + diff --git a/features/tests/window handling .feature b/features/tests/window handling .feature new file mode 100644 index 00000000..6e85ca2f --- /dev/null +++ b/features/tests/window handling .feature @@ -0,0 +1,12 @@ + + +Scenario: User can open and close Terms and Conditions from sign in page + Given Open sign in page + When Store original window + And Click on Target terms and conditions link + And Switch to the newly opened window + Then Verify Terms and Conditions page is opened + And User can close new window +`And switch back to original + + diff --git a/practice b/practice new file mode 100644 index 00000000..e0f96bdd --- /dev/null +++ b/practice @@ -0,0 +1,13 @@ +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(service=service) +driver.maximize_window() diff --git a/python coding practice and review .py b/python coding practice and review .py new file mode 100644 index 00000000..9081c5ed --- /dev/null +++ b/python coding practice and review .py @@ -0,0 +1,122 @@ + +#Lesson 2 on Numbers and Variables + #integer = whole nunmber 4 + #float = number with decimal point 4.5 + #floor division = counting the quotient using // symbol 9//2=4 + #remainder= remaining number after dividing: 6%4=2 + #exponentiation **, 6**2 = 36 + + #Variables + #Stores information that can be retrieved later on + #can be reassigned values + #cannot be a keyword + #cannot start with a number + #cannot contain spaces + #CAN have an underscore + #CAN have numbers within, just not to begin with + #are case sensitive + #Data Types + #Boolean= True or False values + #Dictionaries --> store multiple items of data as a list-- key:value pairs, values are referenced by key {'name':'Bob} + #Set--> restrictive python list w unique values separated by commas inside curly braces set = {'Alpha',"Bear'} + #string= type of text data type enclosed by quotes, string = 'Number of kids' + #List = allows us to store info in a specific order. We can add, remove, or modify elements after creating the list + #example, list = [1,2,3,4,5] + #Tuple--> a collection of elements which cannot be changed or reversed, represented by parenthesis + #tuple=(1,2,3,4,5) + +#Lesson 3: Strings + #enclosed within single '' or double "" quotes + #can contain letters, numbers, symbols, and even empty spaces + #triple quotes will break down string into multiple lines + #\n breaks code into a separate line + + #concatenation + #uses a + symbol to concatenate or join variables and text together + #Example: +Book ='Coding for Python' +copyright_year = 2002 +print("The book"+Book +"was written in" + str(copyright_year)) + +#.format() method +print('Hi there, {}'.format('Pooja')) +print("{0} and {1}".format('Pooja','Patel')) + +#F-strings + #Do not need to use + symbol or conversions +Age = 31 +Name= 'Pooja' +print(f'{Name} is {Age} years old.') +print(len(Name)) +print(str.upper(Name)) +print(str.lower(Name)) +print(str.count(Name,'oo')) +#str.replace('old','new')--> replacing variables +#str.count('letter')--> counts number of times something appears in a string + + +text = input('Enter the text to be formatted: ') +print("UPPERCASE:" + text.upper()) +print(text.lower()) +print(text.title()) +print(len(text)) + +sentence = input("Enter a sentence: ") +new_word = input("Enter the word to replace: ") +letter = input("Enter the letter to count: ") +print(sentence.replace(new_word, sentence)) +print(sentence.count(letter)) + + +#Slicing + #index--> refers to numerical position of an element within a string, uses square brackets [] to indicate index position + # indices can be positive or negative, starts with 0 from the left side and -1 on the right side +string = "Python" +print(string[0:3]) #--> regular string +print(string[-1:-3:-1]) #--> reversing a string + +sliced_sentence = 'Python programming is fun!' +print(sliced_sentence[7:18]) +print(sliced_sentence[0:25:3]) +print(sliced_sentence[::-1]) + + +#Lesson 4: Boolean + #data type that has only 2 possible values, True or False + #conditional operators + # < less than + # < = less than or equal to + # > greater than + # > = greater than or equal to + # == equal + # != does not equal + #If Statement = evaluates a given condition and if the condition is true, it executes a specific block of code + #Else Statement = executes other code when all other possibilities are false + # Elif Statement = another option to consider + #AND, OR, NOT = Boolean operators + +age = int(input('Enter your age:')) + +if age >= 18: + print('You are eligible to vote') +else: + print('You are not eligible to vote') + + +grade = int(input("Enter student’s grade: ")) + +if grade >= 90: + print('You\'ve got an A') +elif grade >= 80: + print('You\'ve got an B') +elif grade >= 70: + print('You\'ve got an C') +elif grade >= 60: + print('You\'ve got an D') +else: + print('You\'ve got an F') + +#Lesson on Lists: + # iterate means to walk over each + # first element of a list has an index of 0 + # lists are always declared using square brackets \ No newline at end of file diff --git a/python/__init__.py b/python/__init__.py new file mode 100644 index 00000000..82dbdcfa --- /dev/null +++ b/python/__init__.py @@ -0,0 +1,29 @@ +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(service=service) +driver.maximize_window() + +# open the url +driver.get('https://www.amazon.com/') + +# Locate element: +# driver.find_element() # By. / value +# Locate by ID: +driver.find_element(By.ID, 'twotabsearchtextbox') +driver.find_element(By.ID, 'nav-logo-sprites') + +# By Xpath, using 1 attribute +driver.find_element(By.XPATH, "//img[@alt='Shop Studio Pro headphones']") +driver.find_element(By.XPATH, "//input[@name='field-keywords']") +driver.find_element(By.XPATH, "//input[@placeholder='Search Amazon']") +# By Xpath, multiple attributes +driver.find_element(By.XPATH, "//a[@class='nav-a ' and @href='/gp/bestsellers/?ref_=nav_cs_bestsellers' and @tabindex='0']") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100755 index 28461e89..00000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -allure-behave -behave -selenium -webdriver-manager \ No newline at end of file diff --git a/sample_script.py b/sample_script.py index 3925e946..41d1f882 100755 --- a/sample_script.py +++ b/sample_script.py @@ -11,6 +11,7 @@ service = Service(driver_path) driver = webdriver.Chrome(service=service) driver.maximize_window() +driver.implicitly_wait(3) # open the url driver.get('https://www.google.com/') @@ -18,7 +19,7 @@ # populate search field search = driver.find_element(By.NAME, 'q') search.clear() -search.send_keys('Car') +search.send_keys('table') # wait for 4 sec sleep(4) @@ -27,7 +28,7 @@ driver.find_element(By.NAME, 'btnK').click() # verify search results -assert 'car'.lower() in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}" +assert 'table'.lower() in driver.current_url.lower(), f"Expected query not in {driver.current_url.lower()}" print('Test Passed') driver.quit()