import os import sys import time from urllib.parse import urlencode import allure import requests from _pytest.fixtures import fixture from playwright.sync_api import sync_playwright from src import config from src.helpers.logger import Logger from src.helpers.user_utils import get_state_path from src.pages.album_page.album_header import AlbumPageHeader from src.pages.album_page.performance.coutries_tab import AlbumPageCountriesTab from src.pages.apollo_header_main import ApolloHeader from src.pages.artist_page.artist_header import ArtistPageHeader from src.pages.artist_page.details.tracks_table import ArtistPageTracksTable from src.pages.artist_page.performance.artist_sas_tab import ArtistPageSASTab from src.pages.base import App from src.pages.charts_digest_page.bubbling_under import CDBubblingUnder from src.pages.charts_digest_page.major_moves import CDMajorMoves from src.pages.charts_digest_page.top_10_section import CDTop10Section from src.pages.date_picker.single_datepicker import SingleDatePicker from src.pages.juno_page.juno_page import JunoPage from src.pages.login_page import LoginPage from src.pages.popup import Popup from src.pages.top_charts_page.tc_amazon_tab import TopChartsAmazonTab from src.pages.top_charts_page.tc_apple_tab import TopChartsAppleTab from src.pages.top_charts_page.tc_shazam_tab import TopChartsShazamTab from src.pages.top_charts_page.tc_spotify_tab import TopChartsSpotifyTab from src.pages.top_charts_page.tc_trending_tab import TopChartsTrendingTab from src.pages.top_charts_page.top_charts_page import TopChartsPage from src.pages.track_page.header.track_page_header import TrackPageHeader from src.pages.track_page.performance_section.by_markets_tab import TrackPagePerformanceByMarketsTab from src.pages.track_page.performance_section.streams_and_sources_tab import TrackPagePerformanceSASTab from src.pages.track_page.performance_section.tiktok_tab import TrackPagePerformanceTiktokTab from src.pages.track_page.performance_section.youtube_tab import TrackPagePerformanceYoutubeTab from src.pages.track_page.performance_section.youtube_video_window import YoutubeWindow log = Logger() access_token = {} @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(): url = config.ENV_BASE_URL log.info(f"Target URL = '{url}'") yield url @fixture(scope='function') def get_user_token(get_url): # log.info('getting user token from context file') # file_name = 'state.json' # if os.path.exists(file_name): # with open(file_name) as state_json: # state = json.load(state_json) # log.info(f"STATE: {state}") # ls = state['origins'][0]['localStorage'] # for item in ls: # if item['name'] == 'authData': # data = json.loads(item['value']) # token = str(dict(data).get("idToken")) # log.info(f'getting user token from context file: {token}') # else: session = requests.session() global access_token user = config.USER_EMAIL password = config.USER_PASSWORD if access_token.get(user): return access_token.get(user) data = { "client_id": config.AUTH0_CLIENT_ID, "client_secret": config.AUTH0_CLIENT_SECRET, "audience": config.AUTH0_AUDIENCE, "grant_type": config.AUTH0_GRANT_TYPE, "realm": config.AUTH0_REALM, "username": user, "password": password, } headers = {"content-type": "application/x-www-form-urlencoded"} session_token = session.post(config.AUTH0_HOST, urlencode(data), headers=headers) access_token[user] = session_token.json().get("access_token") # refresh token -> access token new log.info(access_token[user]) if access_token[user] == None: raise ValueError('Can not get the access token!') token = access_token[user] return token @fixture(scope="function") def app(get_playwright, get_browser, get_user_token, 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) state_file = get_state_path() if os.path.exists(state_file) and os.stat(state_file).st_size > 0: browser_config.update({"storage_state": state_file}) log.info(f"Browser configurations:\n '{browser_config}'") app = App(browser=get_browser, user_token=get_user_token, base_url=get_url, **browser_config) if request.cls is not None: request.cls.app = app request.cls.login_page = LoginPage(app.page) request.cls.apollo_header = ApolloHeader(app.page) request.cls.single_date_picker = SingleDatePicker(app.page) request.cls.cd_top_10_section = CDTop10Section(app.page) request.cls.cd_major_moves = CDMajorMoves(app.page) request.cls.cd_bubbling_under = CDBubblingUnder(app.page) request.cls.top_charts_page = TopChartsPage(app.page) request.cls.top_charts_amazon_tab = TopChartsAmazonTab(app.page) request.cls.top_charts_shazam_tab = TopChartsShazamTab(app.page) request.cls.top_charts_trending_tab = TopChartsTrendingTab(app.page) request.cls.top_charts_apple_tab = TopChartsAppleTab(app.page) request.cls.top_charts_spotify_tab = TopChartsSpotifyTab(app.page) request.cls.popup = Popup(app.page) request.cls.juno_page = JunoPage(app.page) request.cls.track_page_header = TrackPageHeader(app.page) request.cls.tp_sas_tab = TrackPagePerformanceSASTab(app.page) request.cls.tp_by_markets_tab = TrackPagePerformanceByMarketsTab(app.page) request.cls.tp_youtube_tab = TrackPagePerformanceYoutubeTab(app.page) request.cls.youtube_video_popup = YoutubeWindow(app.page) request.cls.tp_tiktok_tab = TrackPagePerformanceTiktokTab(app.page) request.cls.album_header = AlbumPageHeader(app.page) request.cls.album_countries_tab = AlbumPageCountriesTab(app.page) request.cls.artist_header = ArtistPageHeader(app.page) request.cls.artists_sas_tab = ArtistPageSASTab(app.page) request.cls.artists_tracks_table = ArtistPageTracksTable(app.page) # app.page.route(re.compile(r"(\.png$)|(\.jpg$)|(\.jpeg$)|(\.svg$)|(\.woff2$)"), lambda route: route.abort()) 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)