diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..51227d7 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 0f2dc0c..e4cd1ae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /local.log -env +.env diff --git a/browserstack.err b/browserstack.err new file mode 100644 index 0000000..a6e1414 --- /dev/null +++ b/browserstack.err @@ -0,0 +1 @@ +[object Object] \ No newline at end of file diff --git a/browserstack.yml b/browserstack.yml deleted file mode 100644 index d698962..0000000 --- a/browserstack.yml +++ /dev/null @@ -1,63 +0,0 @@ -# ============================= -# Set BrowserStack Credentials -# ============================= -# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and -# BROWSERSTACK_ACCESS_KEY as env variables -userName: YOUR_USERNAME -accessKey: YOUR_ACCESS_KEY - -# ====================== -# BrowserStack Reporting -# ====================== -# The following capabilities are used to set up reporting on BrowserStack: -# Set 'projectName' to the name of your project. Example, Marketing Website -projectName: BrowserStack Samples -# Set `buildName` as the name of the job / testsuite being run -buildName: browserstack build -# `buildIdentifier` is a unique id to differentiate every execution that gets appended to -# buildName. Choose your buildIdentifier format from the available expressions: -# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution -# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 -# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests -buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} - -# ======================================= -# Platforms (Browsers / Devices to test) -# ======================================= -# Platforms object contains all the browser / device combinations you want to test on. -# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) -platforms: - - os: OS X - osVersion: Big Sur - browserName: Chrome - browserVersion: latest - - os: Windows - osVersion: 10 - browserName: Edge - browserVersion: latest - - deviceName: Samsung Galaxy S22 Ultra - browserName: chrome # Try 'samsung' for Samsung browser - osVersion: 12.0 - -# ========================================== -# BrowserStack Local -# (For localhost, staging/private websites) -# ========================================== -# Set browserStackLocal to true if your website under test is not accessible publicly over the internet -# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction -browserstackLocal: true # (Default false) -# browserStackLocalOptions: -# Options to be passed to BrowserStack local in-case of advanced configurations - # localIdentifier: # (Default: null) Needed if you need to run multiple instances of local. - # forceLocal: true # (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. - # Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections - -source: python-browserstack:sample-sdk:v1.0 - -# =================== -# Debugging features -# =================== -debug: false # # Set to true if you need screenshots for every selenium command ran -networkLogs: false # Set to true to enable HAR logs capturing -consoleLogs: errors # Remote browser's console debug levels to be printed (Default: errors) -# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) diff --git a/browserstack_template.yml b/browserstack_template.yml new file mode 100644 index 0000000..7e917ce --- /dev/null +++ b/browserstack_template.yml @@ -0,0 +1,14 @@ +userName: ${BROWSERSTACK_USERNAME} +accessKey: ${BROWSERSTACK_ACCESS_KEY} +framework: pytest +platforms: + - os: Windows + osVersion: 10 + browserName: Chrome + browserVersion: 120.0 +browserstackLocal: true +buildName: browserstack-build-1 +projectName: Piyush-onboarding-31 +percy: true +percyCaptureMode: auto +accessibility: true diff --git a/configBSfile.py b/configBSfile.py new file mode 100644 index 0000000..ef1d166 --- /dev/null +++ b/configBSfile.py @@ -0,0 +1,19 @@ +import os +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + +# Read the YAML file as a string +with open("browserstack_template.yml", "r") as file: + content = file.read() + +# Replace placeholders with environment variables +content = content.replace("${BROWSERSTACK_USERNAME}", os.getenv("BROWSERSTACK_USERNAME", "")) +content = content.replace("${BROWSERSTACK_ACCESS_KEY}", os.getenv("BROWSERSTACK_ACCESS_KEY", "")) + +# Write the updated YAML back to a file or use it directly +with open("browserstack.yml", "w") as file: + file.write(content) + +print("Updated browserstack.yml written to browserstack_resolved.yml") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6bb0568..bd59701 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,6 @@ browserstack-local >= 1.2.3 selenium browserstack-sdk +pytest +python-dotenv +percy-selenium diff --git a/tests/__pycache__/pytest-local.cpython-313-pytest-8.3.4.pyc b/tests/__pycache__/pytest-local.cpython-313-pytest-8.3.4.pyc new file mode 100644 index 0000000..c39a506 Binary files /dev/null and b/tests/__pycache__/pytest-local.cpython-313-pytest-8.3.4.pyc differ diff --git a/tests/__pycache__/test_local.cpython-313-pytest-8.3.4.pyc b/tests/__pycache__/test_local.cpython-313-pytest-8.3.4.pyc new file mode 100644 index 0000000..2be1379 Binary files /dev/null and b/tests/__pycache__/test_local.cpython-313-pytest-8.3.4.pyc differ diff --git a/tests/selenium-local-testing.py b/tests/selenium-local-testing.py new file mode 100644 index 0000000..45ee613 --- /dev/null +++ b/tests/selenium-local-testing.py @@ -0,0 +1,67 @@ +from selenium import webdriver +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.by import By +from selenium.common.exceptions import NoSuchElementException, TimeoutException + +def run_test(driver): + """Function to execute the test""" + try: + # Open the target website + driver.get('https://bstackdemo.com/') + + # Wait for the page title to contain 'StackDemo' + WebDriverWait(driver, 10).until(EC.title_contains('StackDemo')) + + # Get the text of the product - iPhone 12 + item_on_page = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/p')) + ).text + + # Click the 'Add to cart' button if it is visible + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/div[4]')) + ).click() + + # Check if the Cart pane is visible + WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.CLASS_NAME, 'float-cart__content')) + ) + + # Get the text of the product in the cart + item_in_cart = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="__next"]/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]')) + ).text + + # Verify whether the product (iPhone 12) is added to the cart + if item_on_page == item_in_cart: + print(f"Test Passed: iPhone 12 successfully added to cart on {driver.name}!") + else: + print(f"Test Failed: iPhone 12 not added to cart on {driver.name}!") + except NoSuchElementException as e: + print(f"Test Failed on {driver.name}: Element not found - {e}") + except TimeoutException as e: + print(f"Test Failed on {driver.name}: Operation timed out - {e}") + except Exception as e: + print(f"Test Failed on {driver.name}: An unexpected error occurred - {e}") + finally: + # Stop the driver + driver.quit() + +# Run on Chrome +chrome_driver = webdriver.Chrome() # Ensure ChromeDriver is installed and in PATH +print("Running test on Chrome...") +run_test(chrome_driver) + +# Run on Safari +try: + safari_driver = webdriver.Safari() # SafariDriver is pre-installed on macOS + print("Running test on Safari...") + run_test(safari_driver) +except Exception as e: + print(f"Safari test could not run: {e}") + +# Run on Firefox +firefox_driver = webdriver.Firefox() # Ensure GeckoDriver is installed and in PATH +print("Running test on Firefox...") +run_test(firefox_driver) \ No newline at end of file diff --git a/tests/test.py b/tests/test.py index c242b14..d16fd6c 100644 --- a/tests/test.py +++ b/tests/test.py @@ -6,6 +6,9 @@ from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.chrome.options import Options as ChromeOptions + + + # The webdriver management will be handled by the browserstack-sdk # so this will be overridden and tests will run browserstack - # without any changes to the test files! diff --git a/tests/test_local.py b/tests/test_local.py new file mode 100644 index 0000000..d8ffd69 --- /dev/null +++ b/tests/test_local.py @@ -0,0 +1,59 @@ +import pytest +from selenium import webdriver +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.by import By +from selenium.common.exceptions import NoSuchElementException, TimeoutException + +# Define a pytest fixture for the WebDriver setup and teardown +@pytest.fixture(params=["chrome", "firefox", "safari"], scope="function") +def driver(request): + """Fixture to initialize and clean up the WebDriver.""" + if request.param == "chrome": + driver = webdriver.Chrome() # Ensure ChromeDriver is installed and in PATH + elif request.param == "firefox": + driver = webdriver.Firefox() # Ensure GeckoDriver is installed and in PATH + elif request.param == "safari": + driver = webdriver.Safari() # SafariDriver is pre-installed on macOS + else: + raise ValueError(f"Unsupported browser: {request.param}") + + yield driver # This provides the driver instance to the test + driver.quit() # Quit the driver after the test completes + +def test_add_to_cart(driver): + """Test to verify adding a product to the cart.""" + try: + # Open the target website + driver.get('https://bstackdemo.com/') + + # Wait for the page title to contain 'StackDemo' + WebDriverWait(driver, 30).until(EC.title_contains('StackDemo')) + # Get the text of the product - iPhone 12 + item_on_page = WebDriverWait(driver, 10).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/p')) + ).text + + # Click the 'Add to cart' button if it is visible + WebDriverWait(driver, 30).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="1"]/div[4]')) + ).click() + + # Check if the Cart pane is visible + WebDriverWait(driver, 30).until( + EC.visibility_of_element_located((By.CLASS_NAME, 'float-cart__content')) + ) + # Get the text of the product in the cart + item_in_cart = WebDriverWait(driver, 30).until( + EC.visibility_of_element_located((By.XPATH, '//*[@id="__next"]/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]')) + ).text + + # Verify whether the product (iPhone 12) is added to the cart + assert item_on_page == item_in_cart, f"Expected item: {item_on_page}, but found: {item_in_cart}" + print(f"Test Passed: iPhone 12 successfully added to cart on {driver.name}!") + except NoSuchElementException as e: + pytest.fail(f"Test Failed on {driver.name}: Element not found - {e}") + except TimeoutException as e: + pytest.fail(f"Test Failed on {driver.name}: Operation timed out - {e}") + except Exception as e: + pytest.fail(f"Test Failed on {driver.name}: An unexpected error occurred - {e}")