import os import re import sys import time import json import allure import requests from pytest import fixture from playwright.sync_api import sync_playwright from src.helpers import api_helper from src.helpers.logger import Logger from src.helpers.non_mfa import get_non_mfa_url, get_fresh_tokens from src.pages.base import App from src import config from src.pages.common_page import CommonPage from src.pages.home_page import HomePage from src.pages.menu_page import MenuPage from src.pages.discovery_page import DiscoveryPage from src.pages.saved_discoveries_page import SavedDiscoveriesPage from src.pages.discovery_results_page import DiscoveryResultsPage from src.pages.categories_page import CategoriesPage from src.pages.search_page import SearchPage from src.pages.artist_page import ArtistPage from src.pages.track_page import TrackPage from src.pages.profile_page import ProfilePage from src.pages.category_page import CategoryPage from src.pages.login_page import LoginPage log = Logger() @fixture(scope="session") def get_playwright(): with sync_playwright() as playwright: yield playwright @fixture(scope="session") def get_browser(get_playwright): browser = config.BROWSER headless = config.HEADLESS devtools = config.DEVTOOLS log.info(f"Chosen browser is '{browser}'") if browser == 'Chrome': bro = get_playwright.chromium.launch(headless=headless, devtools=devtools) elif browser == 'Firefox': bro = get_playwright.firefox.launch(headless=headless) elif browser == 'Safari': bro = get_playwright.webkit.launch(headless=headless) else: assert False, 'Unsupported browser type. Use: Chrome, Firefox, Safari' yield bro bro.close() @fixture(scope='session') def get_url(): if config.NO_MFA == 'True': url = get_non_mfa_url() else: url = config.ENV_BASE_URL yield url @fixture(scope='session') def define_env(): pattern = r'.*?\/\/(.*)\..*\..*' env = re.search(pattern, config.ENV_BASE_URL).group(1) log.info(f'Defined environment = {env}') yield env @fixture(scope='function') def get_user_token(get_url, define_env): env = define_env token = None if config.NO_MFA != 'True': log.info('getting user token from context file') with open('state.json', 'r') as state_json: state = json.load(state_json) for cookie in state['cookies']: if cookie['name'] == f'dna_refresh_token_{env}': refresh_cookie = {cookie['name']: cookie['value']} token, refresh_token = get_fresh_tokens(refresh_cookie) cookie['value'] = refresh_token for cookie in state['cookies']: if cookie['name'] == f'dna_bearer_token_{env}' and cookie['domain'] == '.dna.stream': cookie['value'] = token with open('state.json', 'w') as state_json: json.dump(state, state_json, indent=4) else: url = get_url response = requests.get(url) log.info("User token response = {}".format(response)) key_token = f'dna_bearer_token_{env}' token = response.cookies[key_token] yield token @fixture(scope="function") def api(get_user_token): user_token = get_user_token api = api_helper.ApiHelper(user_token) return api @fixture(scope="function") def app(get_playwright, get_browser, api, get_url, request): browser_config = config.BROWSER_OPTIONS device = config.DEVICE device_config = get_playwright.devices.get(device) if device_config is not None: browser_config.update(device_config) if config.NO_MFA != 'True': browser_config.update({"storage_state": "state.json"}) log.info(f"Browser configurations:\n '{browser_config}'") log.info('config.NO_MFA = {}'.format(config.NO_MFA)) app = App(browser=get_browser, api=api, base_url=get_url, **browser_config) app.api.user_cleanup() if request.cls is not None: request.cls.app = app request.cls.common_page = CommonPage(app.page) request.cls.menu_page = MenuPage(app.page) request.cls.home_page = HomePage(app.page) request.cls.discovery_page = DiscoveryPage(app.page) request.cls.saved_discoveries_page = SavedDiscoveriesPage(app.page) request.cls.discovery_results_page = DiscoveryResultsPage(app.page) request.cls.categories_page = CategoriesPage(app.page) request.cls.search_page = SearchPage(app.page) request.cls.artist_page = ArtistPage(app.page) request.cls.track_page = TrackPage(app.page) request.cls.profile_page = ProfilePage(app.page) request.cls.category_page = CategoryPage(app.page) request.cls.login_page = LoginPage(app.page) yield app if request.node.rep_call.failed: screenshot_on_failure(app.page) expected_visual_screenshot_on_failure(request) app.close() # Start tracing before creating / navigating a page. @fixture(scope="function") def tracing(app): app.start_tracing() yield app.stop_tracing() def screenshot_on_failure(page): file_name = "screenshot" + str(round(time.time() * 1000)) + ".png" if len(file_name) >= 200: file_name = str(round(time.time() * 1000)) + ".png" screenshot_dir = "../../screenshots/" relative_name = screenshot_dir + file_name current_dir = os.path.dirname(__file__) destination_file = os.path.join(current_dir, relative_name) destination_dir = os.path.join(current_dir, screenshot_dir) if not os.path.exists(destination_dir): os.makedirs(destination_dir) page.screenshot(path=destination_file, full_page=True) screenshot_bytes = page.screenshot() allure.attach(screenshot_bytes, name=file_name, attachment_type=allure.attachment_type.PNG) def expected_visual_screenshot_on_failure(request): snapshot_tests_failures_path = f'src/tests/gui/visual_tests/snapshot_tests_failures/' \ f'{request.module.__name__}/{request.function.__name__}[chromium][{sys.platform}]' if 'snapshot_tests_failures' in os.listdir(f'src/tests/gui/visual_tests'): print(os.listdir(f'src/tests/gui/visual_tests/snapshot_tests_failures/{request.module.__name__}')) files = os.listdir(snapshot_tests_failures_path) for file in files: with open(f'{snapshot_tests_failures_path}/{file}', 'rb') as image: f = image.read() b = bytearray(f) allure.attach(b, name=file, attachment_type=allure.attachment_type.PNG)