import json import re from urllib import parse from urllib.parse import unquote from allure import step from assertpy import assert_that from playwright.sync_api import Browser, expect from src.helpers import api_helper from src.helpers.logger import Logger log = Logger() class App: def __init__(self, browser: Browser, user_token: str, base_url: str, **kwargs): self.browser = browser self.context = self.browser.new_context(**kwargs) self.page = self.context.new_page() self.base_url = base_url self.api = api_helper.ApiHelper(user_token) @step("Go to {endpoint} page") def go_to(self, endpoint: str, wait=False): self.page.goto(self.base_url + endpoint) if wait: self.page.wait_for_load_state('networkidle', timeout=20000) def close(self): self.page.close() self.context.close() def start_tracing(self): self.context.tracing.start(screenshots=True, snapshots=True, sources=True) def stop_tracing(self): self.context.tracing.stop(path="trace.zip") def check_http_response(self): # https://playwright.dev/python/docs/network#network-events pass # NOTE: BUG for Chromium https://github.com/microsoft/playwright/issues/6479 def read_network_requests(self): self.page.on("request", lambda request: print(">>", request.method, request.url, request.post_data)) def verify_url_params(self, params): for k, v in dict(params).items(): expect(self.page).to_have_url(re.compile(r"{}={}".format(k, v))) def get_parameter_from_url(self, parameter): expect(self.page).to_have_url(re.compile(r"{}".format(parameter))) url = self.page.url params = dict(parse.parse_qsl(parse.urlsplit(url).query)) url_param = params[parameter] return url_param def change_param_in_url(self, param, new): if param in self.page.url: url_to_go = self.page.url.replace(f"{param}={self.get_parameter_from_url(param)}", f"{param}={new}") else: url_to_go = f'{self.page.url}&{param}={new}' print(f"url: {url_to_go}") self.go_to(url_to_go) def get_amplitude_requests(self): items = [] self.page.on("request", lambda request: items.extend(self.parse_amplitude_payload(request.post_data)) if 'amplitude' in request.url else None) items = [r for r in items if r is not None] return items def parse_amplitude_payload(self, payload): postData = unquote(payload) found = re.search(r"e=(.*|\s|\S)&upload_time", postData).group(1) found = json.loads(found) return found def verify_amplitude_events(self, payloads, event_type, event_properties=False, user_properties=False, count=False): formattes_items = {} for i in payloads: if i['event_type'] != '$identify': formattes_items[i['event_type']] = {} formattes_items[i['event_type']].update({'event_properties': i['event_properties']}) formattes_items[i['event_type']].update({'user_properties': i['user_properties']}) if count: assert_that(len(formattes_items)).is_greater_than_or_equal_to(count) if event_type: assert_that(list(formattes_items.keys())).contains(event_type) if event_properties: assert_that(formattes_items[event_type]['event_properties']).is_equal_to(event_properties) if user_properties: assert_that(formattes_items[event_type]['user_properties']).is_equal_to(user_properties) del formattes_items[event_type]