diff --git a/browserstack.yml b/browserstack.yml new file mode 100644 index 0000000..a7afbd9 --- /dev/null +++ b/browserstack.yml @@ -0,0 +1,77 @@ +# ============================= +# 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} +# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng` +# This property is needed to send test context to BrowserStack (test name, status) +framework: pytest +useW3C: false +# ======================================= +# 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: Windows + osVersion: 11 + browserName: chrome + browserVersion: latest + - os: OS X + osVersion: Ventura + browserName: playwright-webkit + browserVersion: latest + - os: Windows + osVersion: 11 + browserName: playwright-firefox + browserVersion: latest +# ======================= +# Parallels per Platform +# ======================= +# The number of parallel threads to be used for each platform set. +# BrowserStack's SDK runner will select the best strategy based on the configured value +# +# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack +# +# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack +parallelsPerPlatform: 1 + +# ========================================== +# 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: pytest-playwright-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/conftest.py b/conftest.py index bda6698..a0791ad 100644 --- a/conftest.py +++ b/conftest.py @@ -11,6 +11,7 @@ import time from playwright.sync_api import Playwright +from playwright.sync_api import Page lock = Lock() threaded_count = 0 @@ -24,16 +25,13 @@ CONFIG = json.load(data_file) - - BROWSERSTACK_USERNAME = os.environ['BROWSERSTACK_USERNAME'] if 'BROWSERSTACK_USERNAME' in os.environ else CONFIG["user"] BROWSERSTACK_ACCESS_KEY = os.environ['BROWSERSTACK_ACCESS_KEY'] if 'BROWSERSTACK_ACCESS_KEY' in os.environ else CONFIG[ "key"] - -if os.environ['REMOTE'] == "true": - @pytest.fixture(scope='session') +if os.environ.get('REMOTE', 'true') == "true": + @pytest.fixture(scope='function') def session_capabilities(playwright: Playwright): global timenow global lock @@ -50,14 +48,15 @@ def session_capabilities(playwright: Playwright): print("capabilities => " + json.dumps(capabilities)) stringifiedCaps = urllib.parse.quote(json.dumps(capabilities)) caps = 'wss://cdp.browserstack.com/playwright?caps=' + stringifiedCaps - browser = playwright.chromium.connect(str(caps)) + browser = playwright.chromium.launch() context = browser.new_context() page = context.new_page() + yield page context.close() browser.close() else: - @pytest.fixture(scope='session') + @pytest.fixture(scope='function') def session_capabilities(playwright: Playwright): capabilities = CONFIG['environments'][TASK_ID] if "browser" in capabilities and capabilities['browser'] == 'chrome': diff --git a/src/tests/__pycache__/sample-test.cpython-39-pytest-7.4.4.pyc b/src/tests/__pycache__/sample-test.cpython-39-pytest-7.4.4.pyc new file mode 100644 index 0000000..44c5553 Binary files /dev/null and b/src/tests/__pycache__/sample-test.cpython-39-pytest-7.4.4.pyc differ diff --git a/src/tests/__pycache__/sample-test1.cpython-39-pytest-7.4.4.pyc b/src/tests/__pycache__/sample-test1.cpython-39-pytest-7.4.4.pyc new file mode 100644 index 0000000..364a83f Binary files /dev/null and b/src/tests/__pycache__/sample-test1.cpython-39-pytest-7.4.4.pyc differ diff --git a/src/tests/__pycache__/sample-test2.cpython-39-pytest-7.4.4.pyc b/src/tests/__pycache__/sample-test2.cpython-39-pytest-7.4.4.pyc new file mode 100644 index 0000000..5e90e44 Binary files /dev/null and b/src/tests/__pycache__/sample-test2.cpython-39-pytest-7.4.4.pyc differ diff --git a/src/tests/__pycache__/sample-test3.cpython-39-pytest-7.4.4.pyc b/src/tests/__pycache__/sample-test3.cpython-39-pytest-7.4.4.pyc new file mode 100644 index 0000000..e642879 Binary files /dev/null and b/src/tests/__pycache__/sample-test3.cpython-39-pytest-7.4.4.pyc differ diff --git a/src/tests/sample-test1.py b/src/tests/sample-test1.py new file mode 100644 index 0000000..60337e0 --- /dev/null +++ b/src/tests/sample-test1.py @@ -0,0 +1,54 @@ +import pytest +from playwright.sync_api import expect + + +def test_sample(session_capabilities, base_url) -> None: + try: + # Load the PAge returned by the fixture + page = session_capabilities + print(page) + # Navigate to the base url + page.goto(base_url, timeout=0) + + # Add the first item to cart + page.locator("[id=\"\\31 \"]").get_by_text("Add to cart").click() + phone = page.locator("[id=\"\\31 \"]").locator(".shelf-item__title").all_inner_texts() + print("Phone =>" + str(phone[0])) + + # Get the items from Cart + qty = page.locator(".bag__quantity").all_inner_texts() + print("Bag quantity => " + str(qty[0])) + + # Verify if there is a shopping cart + expect(page.locator(".bag__quantity")).to_have_count(1) + # Verify if there is only one item in the shopping cart + expect(page.locator(".bag__quantity")).to_have_text("1") + + # Log information to console + log_contextual_info("The cart has one item", "info", page) + + # Get the handle for cart item + cart_item = page.locator(".shelf-item__details") + + # Verify if the cart has the right item + #expect(cart_item.locator(".title")).to_have_text(phone) + print("Cart item => "+cart_item.locator(".title").all_inner_texts()[0]) + assert cart_item.locator(".title").all_inner_texts()[0]==phone[0] + + # Update the test result + mark_test_status("passed", "The cart has " + str(cart_item.locator(".title").all_inner_texts()[0]), page) + except Exception as err: + # Extract error message from Exception + error = str(err).split("Call log:")[0].replace("\n", " but ").replace(":", "=>").replace("'", "") + mark_test_status("failed", error, page) + raise ValueError(error) + + +def mark_test_status(status, reason, page): + page.evaluate("_ => {}", + "browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"" + status + "\", \"reason\": \"" + reason + "\"}}"); + + +def log_contextual_info(desc, loglevel, page): + page.evaluate("_ => {}", + "browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"" + desc + "\", \"level\": \"" + loglevel + "\"}}");