import datetime import json import logging import math import re import time import allure from assertpy import assert_that from natsort import natsorted from selenium.webdriver import ActionChains from ui_automation_framework.core import BasePage, TestStatus from ui_automation_framework.utils import AppConfig, CoreConfig from ui_automation_framework.utils import logger as cl from app.api_client import ApiClient from app.mysql_db_client_custom import MySqlClient from app.src.pages.comparison_page import TrackComparisonPage from app.src.pages.my_starred_tracks_page import MyStarredTracksPage from app.src.pages.third_party.applecharts_page import AppleCharts from app.src.pages.track_page import TrackPage class ApplePlaylistPage(BasePage): log = cl.Logger(logging.DEBUG) TL_COLUMN_STARRED = "starred" TL_COLUMN_POSITION = "position" TL_COLUMN_POSITION_TREND = "position-change" TL_COLUMN_TRACK_ART = "cover" TL_COLUMN_COUNTRY = "country" TL_COLUMN_TRACKS = "track" TL_COLUMN_RELEASE_DATE = "release-date" TL_COLUMN_IN_PLAYLIST_DAYS = "days-in-playlist" TL_COLUMN_AVG_STREAMS = "streams-average" TL_COLUMN_STREAMS_INDEX = "streams-index" TL_COLUMN_APPLE_ICON = "actions" TL_COLUMN_DETAILS_LINK = "details-link" TOOLTIP_POSITION = "Position" TOOLTIP_GLOBAL = "Global Streams in Playlist" TOOLTIP_MARKET = "{} Streams in Playlist" TOOLTIP_MINIMUM = "Minimum" TOOLTIP_PEAK = "Peak" tl_column_values_locator = "//*[contains(@id, 'apple-playlist-table-cell-{column}-')]" track_names_only_locator = "apple-playlist-table-cell-track-name" artist_names_only_locator = "//*[contains(@id, 'apple-playlist-table-cell-name')]/*" timestamp_pattern_no_am_pm = "(\d+)\/(\d+)\/(\d{4}), (\d+):(\d{2})" timestamp_pattern = "(\d{2})\/(\d{2})\/(\d{2}), (\d+):(\d{2}) (AM|PM)" hd_filter_market = "hd_filter_market" TOP_6_MARKETS_FULL_NAME = ["United States", "Canada", "United Kingdom", "Germany", "Australia", "France"] dp_predefined_periods = ["2-weeks", "4-weeks", "8-weeks", "12-weeks", "26-weeks", "1-year"] dp_predefined_count_days = [2 * 7, 4 * 7, 8 * 7, 12 * 7, 26 * 7, 365] dots_colors = ["100,100,100,1", "34,150,243,1", "75,175,80,1"] title_id = "apple-playlist-title" def __init__(self, driver): super().__init__(driver) self.driver = driver self.apple_playlist_page = self.get_page_locators("ApplePlaylistPage", "apple_playlist_elements.json") self.trackPage = TrackPage(self.driver) self.comparison_page = TrackComparisonPage(self.driver) self.apple_charts = AppleCharts(self.driver) self.api_client = ApiClient() self.sql_client = MySqlClient() self.ts = TestStatus(self.driver) self.my_starred_tracks_page = MyStarredTracksPage(self.driver) @allure.step("Navigating to the specified apple playlist page") def open_apple_playlist_page(self, id): self.driver.get("{core_url}/apple/playlist/{playlist_id}".format(core_url=CoreConfig.ENV_BASE_URL, playlist_id=id)) @allure.step("Navigating to the specified apple playlist page with market") def open_apple_playlist_page_with_market(self, id, market): self.driver.get(f"{CoreConfig.ENV_BASE_URL}/apple/playlist/{id}?hd_filter_market={market}") assert_that(self.is_element_displayed(self.title_id)).is_true() @allure.step("Apple playlist page - donuts are displayed") def are_donuts_displayed(self): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "donut_charts")) donuts = self.get_elements(*self.locator(self.apple_playlist_page, "donut_charts")) self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "donut_text_frontline")) frontline = self.is_element_displayed(*self.locator(self.apple_playlist_page, "donut_text_frontline")) self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "donut_text_local")) local = self.is_element_displayed(*self.locator(self.apple_playlist_page, "donut_text_local")) assert_that(donuts).is_length(2) assert_that(frontline).is_equal_to(local).is_true() @allure.step("Apple playlist page - calculate frontline tracks percentage") def get_frontline_tracks_percentage_api(self, id, country): resp = self.api_client.get_apple_tracklist(id=id, country=country)["tracklist"] default_date = "2017-01-01" dates = [] for id in resp: if id["albumReleaseDate"] is not None: dates.append(datetime.datetime.strptime(id["albumReleaseDate"], "%Y-%m-%d").date()) else: dates.append(datetime.datetime.strptime(default_date, "%Y-%m-%d").date()) less_than_30_m = [] for d in dates: self.log.info("date: {}".format(d)) if (datetime.datetime.today().date() - d).days < 913: less_than_30_m.append(d) self.log.info("count less than 30m: {}".format(len(less_than_30_m))) self.log.info("count of all: {}".format(len(dates))) percentage = int((len(less_than_30_m) / len(dates)) * 100) self.log.info("percentage: {}".format(percentage)) return percentage def get_percentage_ui(self): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "percentage")) self.page_has_loaded() time.sleep(3) elements = self.get_elements(*self.locator(self.apple_playlist_page, "percentage")) percentage = [] for e in elements: percentage.append(int(str(self.get_text(element=e)).replace("%", ""))) self.log.info("percentage: {}".format(percentage)) return percentage @allure.step("Apple playlist page - get percentage ui frontline") def get_percentage_frontline_ui(self): return self.get_percentage_ui()[0] @allure.step("Apple playlist page - get percentage ui local") def get_percentage_local_ui(self): return self.get_percentage_ui()[1] @allure.step("Apple playlist page - calculate local tracks percentage") def get_local_tracks_percentage_api(self, id, country): resp = self.api_client.get_apple_tracklist(id=id, country=country)["tracklist"] isrcs_all = [] for id in resp: isrcs_all.append(id) self.log.info("all isrcs: {}".format(isrcs_all)) local_isrcs = [] for id in isrcs_all: if (country == "us") and (str(id["isrc"])[:2] in ["US", "QM", "QZ"]): local_isrcs.append(id["isrc"]) elif (country == "gb") and (str(id["isrc"])[:2] in ["UK", "GB"]): local_isrcs.append(id["isrc"]) elif (country == "br") and (str(id["isrc"])[:2] in ["BR", "BX"]): local_isrcs.append(id["isrc"]) elif (country == "fr") and (str(id["isrc"])[:2] in ["FR", "FX"]): local_isrcs.append(id["isrc"]) elif country == str(str(id["isrc"])[:2]).lower(): local_isrcs.append(id["isrc"]) self.log.info('local isrc" {}'.format(local_isrcs)) percentage = int((len(local_isrcs) / len(isrcs_all)) * 100) self.log.info("percentage: {}".format(percentage)) return percentage @allure.step("Apple playlist page - get selected market") def get_selected_market(self): element = self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "market_switcher")) return str(self.get_text(element=element)) @allure.step("Apple playlist page - change market") def change_market(self, name): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "market_switcher")) self.page_has_loaded() current_market = self.get_selected_market() if current_market != name: self.market_droplist_click() self.choose_market_from_droplist(name) def choose_market_from_droplist(self, name): country = f"//*[contains(@id, '-playlist-market-dd-item-')][contains(@id, '-label')][text()='{name}']" self.click_on_element_js(self.get_element(country, "xpath")) self.page_has_loaded() self.log.info(f"Apple playlist page - changed market to: {name}") current_market = self.get_selected_market() self.ts.markFinal(current_market == name, f"current market: {current_market}\n is equal to: {name}") self.wait_ap_is_loaded() @allure.step("Apple playlist page - verify info icon") def verify_info_icon(self, id): icon = self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "info_icon")) ActionChains(self.driver).move_to_element(to_element=icon).perform() info_icon_tooltip = self.get_text(*self.locator(self.apple_playlist_page, "info_icon_tooltip")) tsp = self.sql_client.get_latest_update_apple_pl_page(id=id) days = tsp.day months = tsp.month hours = tsp.hour minutes = tsp.minute am_pm_add = " AM." if days < 10: days = f"0{days}" if months < 10: months = f"0{months}" if hours < 10: hours = f"0{hours}" elif hours > 12: hours = hours - 12 if hours < 10: hours = f"0{hours}" am_pm_add = " PM." if minutes < 10: minutes = f"0{tsp.minute}" expected_tooltip = f"Playlist data up to {months}/{days}/{str(tsp.year)[2:]}, {hours}:{minutes}{am_pm_add}" assert_that(info_icon_tooltip).is_equal_to(expected_tooltip) assert_that(self.is_element_displayed(element=icon)).is_true() @allure.step("Apple playlist page - verify updated info") def verify_info_updated(self, id): info_updated = self.sql_client.get_updated_apple_playlist_page(id=id) info_updated_ui = str(self.get_text(*self.locator(self.apple_playlist_page, "info_updated"))) updated = "Updated" hours_ago = " hours ago" days_ago = " days ago" yesterday = "yesterday" if "0 hours ago" == info_updated: self.ts.markFinal( info_updated_ui.startswith(updated) and int(info_updated_ui.split(" ")[1]) in list(range(1, 60)) and info_updated_ui.endswith(" minutes ago"), f"update info is: {info_updated_ui}", ) elif hours_ago in info_updated: if f"{updated} an hour ago" == info_updated_ui: pass else: self.ts.markFinal( info_updated_ui.startswith(updated) and int(info_updated_ui.split(" ")[1]) in list(range(2, 24)) and info_updated_ui.endswith(hours_ago), f"update info is: {info_updated_ui}", ) elif yesterday in info_updated_ui: self.ts.markFinal(info_updated == "1 days ago", f"update info is: {info_updated}") else: self.ts.markFinal( info_updated_ui.startswith(updated) and int(info_updated_ui.split(" ")[1]) in list(range(1, 7)) and info_updated_ui.endswith(days_ago), f"update info is: {info_updated_ui}", ) @allure.step("Apple playlist page - click on updated info") def click_on_info_updated(self): self.click_element(*self.locator(self.apple_playlist_page, "info_updated")) @allure.step("Apple playlist page - verify icon time") def verify_icon_time(self, id, na=False): icon_time = self.get_element(*self.locator(self.apple_playlist_page, "icon_time")) ActionChains(self.driver).move_to_element(to_element=icon_time).perform() icon_time_tooltip = self.get_text(locator="//*[contains(@id, 'tooltip')]", locator_type="xpath") tooltip_start = "Tracklist data up to " if na: assert_that(icon_time_tooltip).is_equal_to(f"{tooltip_start}N/A.") else: tsp = self.sql_client.get_icon_time_apple_pl_page(id=id) days = tsp.day months = tsp.month hours = tsp.hour am_pm_add = " AM." if days < 10: days = f"0{days}" if months < 10: months = f"0{months}" if hours < 10: hours = f"0{hours}" elif hours > 12: hours = hours - 12 am_pm_add = " PM." expected_tooltip = f"{tooltip_start}{months}/{days}/{str(tsp.year)[2:]}, {hours}:{tsp.minute}{am_pm_add}" self.ts.markFinal(self.is_element_displayed(element=icon_time), "icon time is displayed") assert_that(icon_time_tooltip).is_equal_to(expected_tooltip) @allure.step("Apple playlist page - verify filter") def verify_filter_initial(self): self.scroll_to_element(*self.locator(self.apple_playlist_page, "filter_input")) filter_input = self.get_element(*self.locator(self.apple_playlist_page, "filter_input")) placeholder = filter_input.get_attribute("placeholder") focused_el = self.driver.switch_to.active_element self.ts.markFinal(self.is_element_displayed(element=filter_input), "filter input is displayed") self.ts.markFinal(placeholder == "Filter", f"Placeholder text is: {placeholder}") self.ts.markFinal(focused_el is not filter_input, "filter input is not focused by default") self.ts.markFinal(self.get_text(element=filter_input) == "", "filter input is empty") @allure.step("Apple playlist page - get displayed track names") def get_from_table(self, column): self.page_has_loaded() time.sleep(3) names_el = self.get_elements(*self.locator(self.apple_playlist_page, f"table_{column}_names")) names = [self.get_text(element=n) for n in names_el] return names @allure.step("Apple playlist page - type to filter") def type_to_filter(self, param): self.scroll_to_element(*self.locator(self.apple_playlist_page, "filter_input")) filter_input = self.get_element(*self.locator(self.apple_playlist_page, "filter_input")) self.click_element(element=filter_input) self.send_text(data=param, element=filter_input) input_text = filter_input.get_attribute("value") self.ts.markFinal(input_text == param, f"filter input text is : {input_text}") self.ts.markFinal( self.is_element_displayed(*self.locator(self.apple_playlist_page, "filter_close_icon")), "clear filter icon is displayed", ) @allure.step("Apple playlist page - clear filter") def filter_clear(self): self.click_element(*self.locator(self.apple_playlist_page, "filter_close_icon")) text = self.get_text(*self.locator(self.apple_playlist_page, "filter_input")) self.ts.markFinal(text == "", "filter is cleared") @allure.step("Apple playlist page - table verify no results") def verify_no_results(self): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "table_no_results")) text = self.get_text(*self.locator(self.apple_playlist_page, "table_no_results")) self.ts.markFinal(text == "No results to show.\nTry another filter.", f"no results text is : {text}") @allure.step("Apple playlist page - verify export button active") def verify_export_button_active(self, active=True, button="button_export"): inactive = self.get_element(*self.locator(self.apple_playlist_page, button)).get_attribute("disabled") if active: self.ts.markFinal(inactive is None, f"export button is active: {inactive}") else: self.ts.markFinal(inactive == "true", f"export button is inactive: {inactive}") @allure.step("Apple playlist page - sort tracklist table by column") def tl_sort_by_column(self, column): self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_header")) self.click_element(locator=f"apple-playlist-table-cell-{column}") @allure.step("Apple playlist page - track list get column values") def tl_get_column_values(self, column): loc = f"//*[contains(@id, 'apple-playlist-table-cell-{column}-')]" if column == self.TL_COLUMN_POSITION: loc = loc + "[not (contains(@id, '-change'))]" elif column == self.TL_COLUMN_COUNTRY: loc = loc + "//../img" elif column == self.TL_COLUMN_DETAILS_LINK: loc = f"//*[contains(@id, '-{self.TL_COLUMN_DETAILS_LINK}')]" elif column == self.TL_COLUMN_TRACKS: loc = "//*[@id='apple-playlist-table-cell-track-name']" self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "button_export")) self.wait_for_element_visible(locator=loc, locator_type="xpath") column_el = self.get_elements(locator=loc, locator_type="xpath")[:5] values = [] if column in [ self.TL_COLUMN_AVG_STREAMS, self.TL_COLUMN_POSITION_TREND, self.TL_COLUMN_POSITION, self.TL_COLUMN_IN_PLAYLIST_DAYS, self.TL_COLUMN_AVG_STREAMS, ]: values = [int(str(self.get_text(element=n)).replace(",", "")) for n in column_el if self.get_text(element=n) != ""] elif column == self.TL_COLUMN_STREAMS_INDEX: for c in column_el: ActionChains(self.driver).move_to_element(to_element=c).perform() tooltip = self.get_text(locator="//div[contains(text(), '%')]", locator_type="xpath") values.append(float(str(tooltip).replace("%", ""))) elif column == self.TL_COLUMN_RELEASE_DATE: values = [datetime.datetime.strptime(str(self.get_text(element=n)), "%m/%d/%y").date() for n in column_el] elif column == self.TL_COLUMN_COUNTRY: full = [c.get_attribute("src") for c in column_el][:5] self.log.info(f"full img links: {full}") values = [str(c).split("/")[-1].split(".")[0].upper() for c in full] elif column == self.TL_COLUMN_DETAILS_LINK: values = column_el else: values = [self.get_text(element=n) for n in column_el] self.log.info(f"values from column: {column}: {values}") return values @allure.step("Apple playlist page - track list choose date") def tl_choose_date(self, param): date_to_choose = f"//*[contains(text(), '{param}, ')]" self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) self.click_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) self.click_on_element_js(self.get_element(locator=date_to_choose, locator_type="xpath")) @allure.step("Apple playlist page - track list get song ids") def tl_get_song_ids(self): self.scroll_to_track_list() column_el = self.get_elements(locator=f'//*[@id="{self.track_names_only_locator}"]/a', locator_type="xpath")[:5] values = [int(str(self.get_attribute_value(element=n, attribute="href")).split("/")[-1]) for n in column_el] self.log.info(f"song ids: {values}") return values @allure.step("Apple playlist page - verify tracklist header") def tl_verify_header(self): self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_header")) header = self.is_element_displayed(*self.locator(self.apple_playlist_page, "tl_header")) self.ts.markFinal(header, f"header is displayed: {header}") @allure.step("Apple playlist page - verify tracklist initial date") def tl_verify_initial_date_dd(self, id, market): self.scroll_to_element(*self.locator(self.apple_playlist_page, "date_graph")) initial = self.get_text(*self.locator(self.apple_playlist_page, "tl_date_dd")) self.click_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) dates_from_dd = self.get_elements( locator="//*[text()='Tracklist']/following-sibling::*/..//div[string-length(text()) > 9]", locator_type="xpath", ) timestamps = [self.get_text(element=d) for d in dates_from_dd] dates_ui = [datetime.datetime.strptime(str(t).split(",")[0], "%m/%d/%y").date() for t in timestamps] timestamps_db = self.sql_client.get_tracklist_histore_dates(id=id, market=market) dates_db = sorted([t.date() for t in timestamps_db], reverse=True) color_before = dates_from_dd[0].value_of_css_property("color") ActionChains(self.driver).move_to_element(to_element=dates_from_dd[0]).pause(2).perform() color_after = dates_from_dd[0].value_of_css_property("color") self.ts.markFinal(all(re.match(pattern=self.timestamp_pattern, string=d) for d in timestamps), f"dates from dd: {timestamps}") self.ts.markFinal(initial == "Current", f"initial chosen date is: {initial}") self.ts.markFinal(dates_ui == dates_db, f"date for db and ui match: diff: {set(dates_ui) - set(dates_db)}") self.ts.markFinal(color_before != color_after, f"is date highlighted: {color_after}\nbefore: {color_before}") self.click_element(*self.locator(self.apple_playlist_page, "tl_header")) @allure.step("Apple playlist page - verify tracklist column names") def verify_columns(self, date="Current"): self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_header")) loc = "apple-playlist-table-cell-" all_columns = [ self.TL_COLUMN_STARRED, self.TL_COLUMN_POSITION, self.TL_COLUMN_POSITION_TREND, self.TL_COLUMN_TRACK_ART, self.TL_COLUMN_COUNTRY, self.TL_COLUMN_TRACKS, self.TL_COLUMN_RELEASE_DATE, self.TL_COLUMN_IN_PLAYLIST_DAYS, self.TL_COLUMN_AVG_STREAMS, self.TL_COLUMN_STREAMS_INDEX, self.TL_COLUMN_APPLE_ICON, ] streams_index_text = "7 Days, Avg\nStreams" if date != "Current": streams_index_text = f"{date}\nStreams" trend_text = "Position\nTrend" in_playlist_text = "In Playlist\nDays" names_expected = [ "Position\n#", trend_text, "Track", "Release Date", in_playlist_text, streams_index_text, "Streams\nIndex", ] if date != "Current": all_columns.remove(self.TL_COLUMN_POSITION_TREND) all_columns.remove(self.TL_COLUMN_IN_PLAYLIST_DAYS) names_expected.remove(trend_text) names_expected.remove(in_playlist_text) column_names = [] for c in all_columns: self.ts.markFinal(self.is_element_displayed(locator=f"{loc}{c}"), f"column: {c} is displayed") text = self.get_text(locator=f"{loc}{c}") if text != "": column_names.append(text) self.ts.markFinal(column_names == names_expected, f"\ncolumn names: {column_names}\nexpected: {names_expected}") def scroll_to_track_list(self): self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_header")) self.wait_ap_is_loaded() def wait_ap_is_loaded(self): self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "button_export")) @allure.step("Apple playlist page - verify tracklist default sorting") def verify_default_sorting(self): self.scroll_to_track_list() positions = self.tl_get_column_values(column=self.TL_COLUMN_POSITION) self.ts.markFinal(positions == sorted(positions), f"\n positions: :{positions}\nexpected: {sorted(positions)}") @allure.step("Apple playlist page - verify tracklist each column sorting") def verify_each_column_sorting(self): self.scroll_to_track_list() for c in [ self.TL_COLUMN_POSITION, self.TL_COLUMN_POSITION_TREND, self.TL_COLUMN_TRACKS, self.TL_COLUMN_RELEASE_DATE, self.TL_COLUMN_IN_PLAYLIST_DAYS, self.TL_COLUMN_AVG_STREAMS, ]: self.verify_export_button_active() self.tl_sort_by_column(column=c) self.verify_export_button_active() desc_values = self.tl_get_column_values(column=c) # if c == self.TL_COLUMN_TRACKS: # desc_values = [str(v).split('\n')[0] for v in desc_values] self.tl_sort_by_column(column=c) asc_values = self.tl_get_column_values(column=c) # if c == self.TL_COLUMN_TRACKS: # asc_values = [str(v).split('\n')[0] for v in asc_values] if c == self.TL_COLUMN_POSITION_TREND: self.ts.markFinal( desc_values == (sorted(desc_values, reverse=True) or sorted(desc_values)), f"values in column: {c} sorted desc: {desc_values}", ) self.ts.markFinal( asc_values == (sorted(asc_values, reverse=True) or sorted(asc_values)), f"values in column: {c} sorted asc: {asc_values}", ) if c not in [self.TL_COLUMN_POSITION_TREND, self.TL_COLUMN_TRACKS]: self.ts.markFinal( desc_values == sorted(desc_values, reverse=True), f"values in column: {c} sorted desc: {desc_values}\nexpected: {sorted(desc_values, reverse=True)}", ) self.ts.markFinal( asc_values == sorted(asc_values), f"values in column: {c} sorted asc: {asc_values}\nexpected: {sorted(asc_values)}", ) elif c == self.TL_COLUMN_TRACKS: desc_values = [str(d).lower() for d in desc_values] asc_values = [str(d).lower() for d in asc_values] self.ts.markFinal( desc_values == natsorted(desc_values, reverse=True) or desc_values == sorted(desc_values, reverse=True), f"values in column: {c} sorted desc: {desc_values}\nexpected: {natsorted(desc_values, reverse=True)} \nor {sorted(desc_values, reverse=True)}", ) self.ts.markFinal( asc_values == natsorted(asc_values) or asc_values == sorted(asc_values), f"values in column: {c} sorted asc: {asc_values}\nexpected: {sorted(asc_values)}", ) @allure.step("Apple playlist page - star track and verify") def star_unstar_track_and_verify(self, market, token): self.refresh() self.scroll_to_track_list() starred_loc = f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_STARRED)}/..//*[contains(@class, 'star')]/parent::*[contains(@id, '')]" starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") apple_id = starred_track_icons[0].get_attribute("id") self.log.info(f"apple id: {apple_id}") isrc = self.api_client.get_isrc_by_apple_id(id=apple_id, market=market)["data"][0]["attributes"]["isrc"] starred_all = self.api_client.get_starred_tracks(token=token)["items"] starred_all = [i["isrc"] for i in starred_all] if isrc in starred_all: self.api_client.delete_apple_starred_track(isrc=isrc, id=apple_id, token=token) self.refresh() self.scroll_to_track_list() self.wait_for_element_visible(locator=starred_loc, locator_type="xpath") starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") color_not_starred_before = starred_track_icons[0].value_of_css_property("color") table_loaded_selector = "//*[contains(@id, 'apple-playlist-table-cell-streams-average-')][string-length(.) > 0]" self.wait_for_element_visible(table_loaded_selector, "xpath") self.click_element(element=starred_track_icons[0]) starred_hint = self.wait_for_element_visible(locator="//*[text()='Track successfully starred']", locator_type="xpath") self.ts.markFinal(self.is_element_displayed(element=starred_hint), "starred hint is displayed") self.click_element(*self.locator(self.apple_playlist_page, "tl_header")) time.sleep(1) self.wait_for_element_visible(locator=starred_loc, locator_type="xpath") starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") color_starred = starred_track_icons[0].value_of_css_property("color") starred_all = self.api_client.get_starred_tracks(token=token)["items"] starred_all = [i["isrc"] for i in starred_all] starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") self.wait_for_element_visible(table_loaded_selector, "xpath") self.click_element(element=starred_track_icons[0]) unstarred_hint = self.wait_for_element_visible(locator="//*[text()='Track successfully unstarred']", locator_type="xpath") self.click_element(*self.locator(self.apple_playlist_page, "tl_header")) time.sleep(1) self.wait_for_element_visible(locator=starred_loc, locator_type="xpath") starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") color_not_starred_after = starred_track_icons[0].value_of_css_property("color") starred_all_not = self.api_client.get_starred_tracks(token=token)["items"] starred_all_not = [i["isrc"] for i in starred_all_not] self.ts.markFinal(isrc in starred_all, f"isrc: {isrc} in starred tracks: {starred_all}") self.ts.markFinal(isrc not in starred_all_not, f"isrc: {isrc} not in starred tracks: {starred_all_not}") self.ts.markFinal( color_not_starred_before == color_not_starred_after, f"\n before not: {color_not_starred_before}\n after not: {color_not_starred_after} are the same", ) self.ts.markFinal( color_not_starred_before != color_starred, f"color after star: {color_starred}\n is different than before: {color_not_starred_before}", ) self.ts.markFinal(self.is_element_displayed(element=unstarred_hint), "unstarred hint is displayed") self.api_client.delete_apple_starred_track(isrc=isrc, id=apple_id, token=token) @allure.step("Star track and verify that it is starred") def star_track_in_apple_playlist(self): self.scroll_to_track_list() locator = f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_STARRED)}/..//*[contains(@class, 'star')]/parent::*[contains(@id, '')]" self.wait_for_element_visible(locator=locator, locator_type="xpath") icons_list = self.get_elements(locator=locator, locator_type="xpath") first_track_star_color = icons_list[0].get_attribute("style") self.log.info(f"star color before: {first_track_star_color}") assert_that(first_track_star_color).is_equal_to(self.my_starred_tracks_page.UNSTARRED_TRACK_ICON_COLOR) self.click_element(element=icons_list[0]) starred_hint = self.wait_for_element_visible(locator="//*[text()='Track successfully starred']", locator_type="xpath") hint = self.get_text(element=starred_hint) assert_that(hint).is_equal_to("Track successfully starred") self.wait_for_element_visible(locator=locator, locator_type="xpath") time.sleep(2) icons_list = self.get_elements(locator=locator, locator_type="xpath") first_track_star_color = icons_list[0].get_attribute("style") self.log.info(f"star color after: {first_track_star_color}") assert_that(first_track_star_color).is_equal_to(self.my_starred_tracks_page.STARRED_TRACK_ICON_COLOR) @allure.step("Unstar track and verify that it is unstarred") def unstar_track_in_apple_playlist(self): self.scroll_to_track_list() locator = f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_STARRED)}/..//*[contains(@class, 'star')]/parent::*[contains(@id, '')]" self.wait_for_element_visible(locator=locator, locator_type="xpath") icons_list = self.get_elements(locator=locator, locator_type="xpath") first_track_star_color = icons_list[0].get_attribute("style") self.log.info(f"star color before: {first_track_star_color}") assert_that(first_track_star_color).is_equal_to(self.my_starred_tracks_page.STARRED_TRACK_ICON_COLOR) self.click_element(element=icons_list[0]) starred_hint = self.wait_for_element_visible(locator="//*[text()='Track successfully unstarred']", locator_type="xpath") hint = self.get_text(element=starred_hint) assert_that(hint).is_equal_to("Track successfully unstarred") self.wait_for_element_visible(locator=locator, locator_type="xpath") time.sleep(2) icons_list = self.get_elements(locator=locator, locator_type="xpath") first_track_star_color = icons_list[0].get_attribute("style") self.log.info(f"star color after: {first_track_star_color}") assert_that(first_track_star_color).is_equal_to(self.my_starred_tracks_page.UNSTARRED_TRACK_ICON_COLOR) @allure.step("Apple playlist page - get tracks ids") def get_playlist_track_data(self, market, track_number): self.refresh() self.scroll_to_track_list() starred_loc = f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_STARRED)}/..//*[contains(@class, 'star')]/parent::*[contains(@id, '')]" starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") apple_id = starred_track_icons[track_number].get_attribute("id") self.log.info(f"apple id: {apple_id}") track_data = self.api_client.get_isrc_by_apple_id(id=apple_id, market=market)["data"][0]["attributes"] self.log.info(f"tracks_data: {track_data}") return track_data @allure.step("Apple playlist page - tl verify country hint") def verify_country_hint(self): self.scroll_to_track_list() countries = self.get_elements(locator=self.tl_column_values_locator.format(column=self.TL_COLUMN_COUNTRY), locator_type="xpath") ActionChains(self.driver).move_to_element(to_element=countries[0]).perform() country_hint = self.get_text(locator="(//iframe/following-sibling::div/*)[2]", locator_type="xpath") self.ts.markFinal(len(country_hint) > 3, f"country hint is : {country_hint}") @allure.step("Apple playlist page - tl verify track name hint") def verify_track_name_hint(self): self.scroll_to_track_list() track_names = self.get_elements(locator=self.track_names_only_locator) track_name = self.get_text(element=track_names[0]) ActionChains(self.driver).move_to_element(to_element=track_names[0]).perform() track_hint = self.get_text(locator="(//iframe/following-sibling::div/*)[2]", locator_type="xpath") self.ts.markFinal(track_hint == track_name, f"track hint is : {track_hint}\n expected: {track_name}") @allure.step("Apple playlist page - tl verify track name link") def verify_track_name_link(self): self.scroll_to_track_list() track_name = self.get_elements(locator=self.track_names_only_locator)[0] name = self.get_text(element=track_name) self.click_element(element=track_name) self.trackPage.is_track_page_title_present(name) @allure.step("Apple playlist page - tl verify artist name hint") def verify_artist_name_hint(self): self.scroll_to_track_list() artist_el = self.get_elements(locator=self.artist_names_only_locator, locator_type="xpath") ActionChains(self.driver).move_to_element(to_element=artist_el[0]).perform() hint = self.is_element_displayed( locator="//*[text()='Artist and album pages are not available for the track.']", locator_type="xpath", ) self.ts.markFinal(hint, "hint for artist name is displayed") @allure.step("Apple playlist page - tl verify In playlist days hint") def verify_hint_in_playlist_days(self): self.scroll_to_track_list() ipd_el = self.get_elements( locator=f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_IN_PLAYLIST_DAYS)}/*", locator_type="xpath", ) ActionChains(self.driver).move_to_element(to_element=ipd_el[0]).perform() hint = self.get_text(locator=self.trackPage.hint_locator, locator_type="xpath") assert_that(re.match(pattern=self.timestamp_pattern, string=hint)).described_as(f"{self.timestamp_pattern},\n {hint}").is_true() @allure.step("Apple playlist page - tl scroll down and verofy back to top button") def scroll_down_verify_back_button(self): self.scroll_to_track_list() for i in list(range(0, 3)): all_rows = self.get_elements(locator=self.artist_names_only_locator, locator_type="xpath") ActionChains(self.driver).move_to_element(all_rows[-1]).perform() self.page_has_loaded() time.sleep(2) back_button = self.get_element(*self.locator(self.apple_playlist_page, "button_back_to_top")) self.verify_columns() self.click_element(element=back_button) top_of_page = self.is_element_displayed(*self.locator(self.apple_playlist_page, "info_updated")) self.ts.markFinal(top_of_page, "page is scrolled to the top") @allure.step("Apple playlist page - tl verify chosen date is in bold") def verify_chosen_date_bold(self, date): date_to_choose = f"//b[contains(text(), '{date}, ')]" self.scroll_to_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) self.click_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) bold_date = self.is_element_present(locator=date_to_choose, locator_type="xpath") self.click_element(*self.locator(self.apple_playlist_page, "tl_date_dd")) self.ts.markFinal(bold_date, "chosen date is bold") @allure.step("Apple playlist page - verify playlist is empty") def verify_playlist_empty(self): empty = self.is_element_displayed(locator="//*[text()='This playlist doesn’t have any tracks yet.']", locator_type="xpath") self.ts.markFinal(empty, "playlist is empty") @allure.step("Apple playlist page - get position trend from the tracklist") def get_position_trends_by_tracks_id(self, market, playlist_id, tracks_id): self.scroll_to_element(*self.locator(self.apple_playlist_page, "date_graph")) api_response = self.api_client.get_apple_tracklist(country=market, id=playlist_id)["tracklist"] if isinstance(tracks_id, str): tracks_id = [tracks_id] trends_api = [] for track_id in tracks_id: for track in api_response: if track["id"] == int(track_id): trends_api.append(track["positionChange"]) trends_api_m = [abs(int(trend)) for trend in trends_api if trend is not None] self.log.info(f"Trend api: {trends_api_m}") return trends_api_m @allure.step("Apple playlist page - open apple playlist page from global search") def global_search_open_apple_playlist(self, playlist, market=AppConfig.get("market")["us"], verify=True): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "global_search")) search = self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "global_search")) ActionChains(self.driver).move_to_element(to_element=search).click().pause(2).click_and_hold(on_element=search).send_keys(str(playlist.name).replace("’", "")).pause(2).send_keys(" ").release().perform() self.page_has_loaded() loc = f"//*[@href='/apple/playlist/{playlist.apple_id}']" self.wait_for_element_visible(locator=loc, locator_type="xpath") e = self.wait_for_element_clickable(locator=loc, locator_type="xpath") self.click_element(element=e) if verify: self.verify_chosen_market(market=market) @allure.step("Apple playlist page - verify market in url and market selector") def verify_chosen_market(self, market): self.wait_ap_is_loaded() market_chosen = self.get_selected_market() self.ts.markFinal(market_chosen == market["name"], f'chosen: {market_chosen}\nexpected: {market["name"]}') self.trackPage.verify_params_in_url({self.hd_filter_market: market["market"]}) @allure.step("Apple playlist page - verify 404 error displayed") def verify_404_page(self): page = self.is_element_displayed(locator='//*[text()="The page you’re looking for is not available."]', locator_type="xpath") self.ts.markFinal(page, "404 page is displayed") @allure.step("Apple playlist page - tl open track page from position") def tl_open_tp_from_position(self, position): self.click_element(element=self.get_elements(locator=self.track_names_only_locator)[position - 1]) @allure.step("Apple playlist page - verify header elements") def verify_header(self): self.click_element(*self.locator(self.apple_playlist_page, "playlist_name")) self.click_element(*self.locator(self.apple_playlist_page, "owner_name")) self.click_element(*self.locator(self.apple_playlist_page, "owner_category")) icon = self.is_element_displayed(*self.locator(self.apple_playlist_page, "playlist_icon")) art = self.is_element_displayed(*self.locator(self.apple_playlist_page, "playlist_art")) name = self.is_element_displayed(*self.locator(self.apple_playlist_page, "playlist_name")) owner_name = self.is_element_displayed(*self.locator(self.apple_playlist_page, "owner_name")) owner_category = self.is_element_displayed(*self.locator(self.apple_playlist_page, "owner_category")) art_link = self.get_art_link() market = self.trackPage.parameter_from_url(self.hd_filter_market) playlist_id = self.get_url().split("/")[-1].split("?")[0] expected_link = f"https://music.apple.com/{market}/playlist/{playlist_id}" assert_that(icon).is_true() assert_that(art).is_true() assert_that(name).is_true() assert_that(owner_name).is_true() assert_that(owner_category).is_true() self.ts.markFinal(expected_link == art_link, f"link: {art_link}\nexpected: {expected_link}") @allure.step("Apple playlist page - verify market drop list filtering flow") def verify_market_droplist_filtering(self): # step 8 filter_text = "g" self.market_droplist_click() filter_el = self.get_element(*self.locator(self.apple_playlist_page, "market_filter")) filter_displayed = self.is_element_displayed(element=filter_el) markets_list_el = self.get_elements(*self.locator(self.apple_playlist_page, "markets_list")) markets_list = [self.get_text(element=m) for m in markets_list_el] self.log.info(f"Markets list: {markets_list}") # step 9 self.clear_text(*self.locator(self.apple_playlist_page, "market_filter")) self.send_text(filter_text, *self.locator(self.apple_playlist_page, "market_filter")) self.page_has_loaded() time.sleep(1) markets_list_el_f = self.get_elements(*self.locator(self.apple_playlist_page, "markets_list")) markets_list_f = [self.get_text(element=m) for m in markets_list_el_f] # step 10 self.click_element(*self.locator(self.apple_playlist_page, "market_filter_close")) self.clear_text(*self.locator(self.apple_playlist_page, "market_filter")) self.page_has_loaded() markets_list_el_after = self.get_elements(*self.locator(self.apple_playlist_page, "markets_list")) markets_list_after = [self.get_text(element=m) for m in markets_list_el_after] # step 11 self.send_text("%", *self.locator(self.apple_playlist_page, "market_filter")) self.page_has_loaded() no_markets = self.is_element_displayed(*self.locator(self.apple_playlist_page, "no_markets_placeholder")) # step 12 self.click_element(*self.locator(self.apple_playlist_page, "market_filter_close")) self.clear_text(*self.locator(self.apple_playlist_page, "market_filter")) self.send_text(AppConfig.get("market")["canada"]["name"], *self.locator(self.apple_playlist_page, "market_filter")) self.choose_market_from_droplist(AppConfig.get("market")["canada"]["name"]) self.market_droplist_click() self.page_has_loaded() markets_list_el_after_c = self.get_elements(*self.locator(self.apple_playlist_page, "markets_list")) markets_list_after_c = [self.get_text(element=m) for m in markets_list_el_after_c] filter_text_after_c = self.get_text(*self.locator(self.apple_playlist_page, "market_filter")) self.ts.markFinal(filter_displayed, "STEP 8: filter is displayed") self.ts.markFinal(set(self.TOP_6_MARKETS_FULL_NAME).issubset(markets_list), "top 6 markets are in markets droplist") # step 10 assert_that(markets_list).is_equal_to(markets_list_after) self.ts.markFinal(markets_list == markets_list_after_c, "STEP 12: after change market market list is reset") self.ts.markFinal(filter_text_after_c == "", "filter test is reset after change market") for t in self.TOP_6_MARKETS_FULL_NAME: markets_list.remove(t) self.ts.markFinal(markets_list == sorted(markets_list), "market list is sorted alphabetical") self.ts.markFinal( all(filter_text in mf.lower() for mf in markets_list_f), f"STEP 9: filter: {filter_text} start working from first letter: \n{markets_list_f}", ) self.ts.markFinal(no_markets, "STEP 11: no markets placeholder is displayed") @allure.step("Apple playlist page - verify donat charts text") def verify_donats_chart_text(self, param): self.scroll_to_element(*self.locator(self.apple_playlist_page, "donut_text_frontline")) front = self.get_text(*self.locator(self.apple_playlist_page, "donut_text_frontline")) local = self.get_text(*self.locator(self.apple_playlist_page, "donut_text_local")) self.ts.markFinal(f"{param.upper()} FRONTLINE TRACKS" == front, f"frontline text: {front}") self.ts.markFinal(f"{param.upper()} LOCAL TRACKS" == local, f"local text: {local}") @allure.step("Apple playlist page - open market droplist") def market_droplist_click(self): self.page_has_loaded() self.scroll_to_element(*self.locator(self.apple_playlist_page, "market_switcher")) self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "market_switcher")) self.click_element(*self.locator(self.apple_playlist_page, "market_switcher")) self.page_has_loaded() @allure.step("Apple playlist page - verify market is bold in droplist") def verify_market_bold(self, param): font = int(self.get_element(locator=f"//*[contains(@id, '-label')][text()='{param}']", locator_type="xpath").value_of_css_property("font-weight")) self.ts.markFinal(font == 800, f"font is : {font}") @allure.step("Apple playlist page - verify no art for playlist") def is_art_missed(self): art_len = len(self.get_elements(*self.locator(self.apple_playlist_page, "playlist_art"))) return art_len == 0 @allure.step("Apple playlist page - verify subtitle") def verify_subtitle(self, param="N/A"): subtitle = self.get_text(*self.locator(self.apple_playlist_page, "playlist_subtitle")) self.ts.markFinal(subtitle == param, f"subtitle is: {subtitle}\nparam: {param}") return subtitle @allure.step("Apple playlist page - get markets from droplist") def get_markets_from_droplist(self): self.market_droplist_click() markets_list_el = self.get_elements(*self.locator(self.apple_playlist_page, "markets_list")) markets_list = [self.get_text(element=m) for m in markets_list_el] self.market_droplist_click() return markets_list @allure.step("Apple playlist page - get art link") def get_art_link(self): art_link = self.get_attribute_value(*self.locator(self.apple_playlist_page, "playlist_art"), attribute="href") return art_link @allure.step("Apple playlist page - open last item from recent search") def recent_search_open_last_item(self): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "global_search")) search = self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "global_search")) ActionChains(self.driver).move_to_element(to_element=search).click().pause(2).release().perform() self.page_has_loaded() loc = "//*[contains(@class, 'search-item-inner')]/..//img" self.wait_for_element_visible(locator=loc, locator_type="xpath") e = self.wait_for_element_clickable(locator=loc, locator_type="xpath") self.click_element(element=e) @allure.step("Apple playlist page - verify export button hover") def verify_export_button_hover(self): self.wait_ap_is_loaded() self.scroll_to_element(*self.locator(self.apple_playlist_page, "date_graph")) export = self.wait_for_element_clickable(*self.locator(self.apple_playlist_page, "button_export")) color_before = export.value_of_css_property("background-color") ActionChains(self.driver).move_to_element(to_element=export).perform() color_after = export.value_of_css_property("background-color") assert_that(color_after).is_not_equal_to(color_before) @allure.step("Apple playlist page - verify csv content") def verify_content_of_csv(self, param=""): self.scroll_to_track_list() self.click_element(*self.locator(self.apple_playlist_page, "button_export")) file_path = f"""http://{CoreConfig.SELENOID_HOST}:4444/download/{self.driver.session_id}/Analyze Playlist - {self.get_playlist_name()}{param}.csv""" self.log.info(f"file path: {file_path}") current_date = self.get_text(*self.locator(self.apple_playlist_page, "tl_date_dd")) columns = ["Position", "Market", "Artist", "Track", "Release Date", "Track URI", "ISRC"] if current_date == "Current": market_streams = "Market Streams Avg, 7 Days" columns.extend(["Added", "Global Streams, 7 Days", "Global Streams Avg, 7 Days", "Market Streams, 7 Days", market_streams]) else: market_streams = "Market Streams" columns.extend(["Global Streams", market_streams]) data = self.trackPage.read_from_csv(file_path) assert_that(columns).is_equal_to(list(data.columns)) positions = self.tl_get_column_values(self.TL_COLUMN_POSITION) markets = self.tl_get_column_values(self.TL_COLUMN_COUNTRY) artists = self.tl_get_artist_names() tracks = self.tl_track_names() release_dates = self.tl_get_column_values(self.TL_COLUMN_RELEASE_DATE) track_uris = self.tl_get_song_ids() market_streams_7 = self.tl_get_column_values(self.TL_COLUMN_AVG_STREAMS) file = {} for c in columns: file[c] = data.get(c).to_list()[: len(positions)] self.log.info(f"file: {file}") release_dates_file = [datetime.datetime.strptime(f, "%m/%d/%y").date() for f in file["Release Date"]] markets_file = [str(f).replace("nan", "_UNKNOWN") for f in file["Market"]] market_streams_7_file = [f for f in file[market_streams] if not math.isnan(f)] self.ts.markFinal(positions == file["Position"], f"position ui: {positions}\nfile: {file['Position']}") self.ts.markFinal(markets == markets_file, f"markets ui: {markets}\nfile: {markets_file}") self.ts.markFinal(artists == file["Artist"], f"artists ui: {artists}\nfile: {file['Artist']}") self.ts.markFinal(tracks == file["Track"], f"tracks ui: {tracks}\nfile: {file['Track']}") self.ts.markFinal(release_dates == release_dates_file, f"release_dates ui: {release_dates}\nfile: {release_dates_file}") self.ts.markFinal(track_uris == file["Track URI"], f"track_uris ui: {track_uris}\nfile: {file['Track URI']}") self.ts.markFinal( market_streams_7 == market_streams_7_file, f"{market_streams} ui: {market_streams_7}\nfile: {market_streams_7_file}", ) return file @allure.step("Apple playlist page - get playlist_name") def get_playlist_name(self): self.page_has_loaded() name = self.get_text(*self.locator(self.apple_playlist_page, "playlist_name")) return name @allure.step("Apple playlist page - get tl artist names") def tl_get_artist_names(self): artist_el = self.get_elements(locator=self.artist_names_only_locator, locator_type="xpath") artists = [self.get_text(element=a) for a in artist_el][:5] return artists @allure.step("Apple playlist page - get tl track names") def tl_track_names(self): track_el = self.get_elements(locator=self.track_names_only_locator) tracks = [self.get_text(element=a) for a in track_el][:5] return tracks @allure.step("Apple playlist page - open details popup") def open_position_details_popup(self, position=0): self.scroll_to_track_list() self.click_element(element=self.tl_get_column_values(self.TL_COLUMN_DETAILS_LINK)[position]) popup_opened = self.is_element_displayed(*self.locator(self.apple_playlist_page, "popup_title")) self.ts.markFinal(popup_opened, "popup details is opened") @allure.step("Apple playlist page - verify track details market") def tdp_verify_local_market(self, market): local_market = self.is_element_displayed(locator=f"//*[text()='{market} streams in playlist']", locator_type="xpath") self.ts.markFinal(local_market, f"local market: {market} is present in details popup") @allure.step("Apple playlist page - verify popup details elements") def verify_popup_elements(self): images = self.get_elements(*self.locator(self.apple_playlist_page, "popup_images")) images = [self.is_element_displayed(element=i) for i in images] popup_items = [ "popup_title", "popup_track_name", "popup_by_artist", "popup_playlist_name", "popup_creator_category", "popup_day_picker", "popup_export_button", "popup_day_count", "popup_chart", ] for i in popup_items: if i == "popup_creator_category" and "/amazon/" in self.get_url(): pass else: item = self.is_element_displayed(*self.locator(self.apple_playlist_page, i)) self.ts.markFinal(item, f"{i} is displayed") self.ts.markFinal(all(i == True for i in images), "images are displayed") @allure.step("Apple playlist page - popup get creator") def popup_get_owner_name(self): subtitle = self.get_text(*self.locator(self.apple_playlist_page, "popup_creator_category")) return subtitle @allure.step("Apple playlist page - popup get owner category") def popup_get_owner_category(self): subtitle = self.get_text(*self.locator(self.apple_playlist_page, "popup_owner_category")).split(" • ")[1] return subtitle @allure.step("Apple playlist page - popup close") def close_popup(self, tp=False): self.click_element(*self.locator(self.apple_playlist_page, "popup_close")) if tp: popup_closed = self.is_element_displayed(locator="track-page-details-tab-barprevious-playlists-tab") else: popup_closed = self.is_element_displayed(*self.locator(self.apple_playlist_page, "playlist_name")) self.ts.markFinal(popup_closed, "popup is closed") @allure.step("Apple playlist page - get playlist owner name") def playlist_get_owner_name(self): loc = "//*[contains(@id, 'apple-playlist-subtitle')]" els = self.get_elements(locator=loc, locator_type="xpath") if len(els) == 1: name = self.get_text(element=els[0]) else: name = self.get_text(*self.locator(self.apple_playlist_page, "owner_name")).replace("By ", "") return name @allure.step("Apple playlist page - popup verify chart elements") def popup_verify_chart_elements(self): self.page_has_loaded() dots = 0 for r in self.dots_colors: dots = dots + len(self.get_elements(locator=f"//*[@fill='rgba({r})'][position() < last()]", locator_type="xpath")) self.ts.markFinal(dots > 0, f"count of all dots: {dots}") for e in ["popup_pip", "popup_sc", "popup_axis_title", "popup_global_value", "popup_local_value"]: visible = self.is_element_displayed(*self.locator(self.apple_playlist_page, e)) self.ts.markFinal(visible, f"element {e} is displayed") for p in ["popup_peak", "popup_minimum"]: el = len(self.get_elements(*self.locator(self.apple_playlist_page, p))) self.ts.markFinal(el > 0, f"count of: {p}: {el}") # for i in ["popup_green", "popup_blue", "popup_grey"]: # ic = len(self.get_elements(*self.locator(self.apple_playlist_page, i))) # self.ts.markFinal(ic > 0, f"count of : {i}: {ic}") @allure.step("Apple playlist page - popup get track metadata") def popup_get_metadata(self): track = self.get_text(*self.locator(self.apple_playlist_page, "popup_track_name")) artist = self.get_text(*self.locator(self.apple_playlist_page, "popup_by_artist")) art = self.get_elements(*self.locator(self.apple_playlist_page, "popup_images"))[0] playlist = self.get_text(*self.locator(self.apple_playlist_page, "popup_playlist_name")) creator = self.get_text(*self.locator(self.apple_playlist_page, "popup_creator_category")) metadata = {"track": track, "artist": artist, "art": art, "playlist": playlist, "creator": creator} self.log.info(f"metadata: {metadata}") return metadata @allure.step("Apple playlist page - click apple icon for position") def click_apple_icon_verify_metadata(self, metadata, position=0): self.scroll_to_track_list() apple_icon = self.get_elements( locator=f"{self.tl_column_values_locator.format(column=self.TL_COLUMN_APPLE_ICON)}/..//a[contains(@href, 'album')]", locator_type="xpath", )[position] self.click_element(element=apple_icon) self.comparison_page.switch_to_tab(2) self.page_has_loaded() time.sleep(2) track = self.get_text(locator="page-container__first-linked-element").strip()[:8] artist = self.get_text(locator="dt-link-to", locator_type="class").strip()[:8] self.ts.markFinal(metadata["track"][:8] == track, f"{metadata['track'][:8]} and {track} match") self.ts.markFinal(metadata["artist"][:8] == artist, f"{metadata['artist'][:8]} and {artist} match") self.comparison_page.close_current_tab() self.comparison_page.switch_to_tab(1) @allure.step("Apple playlist page - popup verify artist tooltip") def popup_verify_artist_tooltip(self): artist = self.get_element(*self.locator(self.apple_playlist_page, "popup_by_artist")) ActionChains(self.driver).move_to_element(to_element=artist).perform() tooltip = self.get_text(*self.locator(self.apple_playlist_page, "artist_tooltip")) text = "Artist and album pages are not available for the track." assert_that(tooltip).is_equal_to(text) @allure.step("Apple playlist page - popup click on track name") def popup_click_on_track_name(self): self.click_element(*self.locator(self.apple_playlist_page, "popup_track_name")) @allure.step("Apple playlist page - popup click on playlist name") def popup_click_on_playlist_name_and_verify(self): name_exp = self.popup_get_playlist_name().replace("’", "").replace("'", "") self.click_element(*self.locator(self.apple_playlist_page, "popup_playlist_name")) name = self.get_playlist_name().replace("’", "").replace("'", "") self.ts.markFinal(name == name_exp, f"{name} and {name_exp} match") @allure.step("Apple playlist page - popup get playlist name") def popup_get_playlist_name(self): name = self.get_text(*self.locator(self.apple_playlist_page, "popup_playlist_name")) return name @allure.step("Apple playlist page - popup click on playlist creator") def popup_click_on_playlist_creator(self): name_exp = self.get_text(*self.locator(self.apple_playlist_page, "popup_creator_category")) self.click_element(*self.locator(self.apple_playlist_page, "popup_creator_category")) name = self.get_text(*self.locator(self.apple_playlist_page, "popup_creator_category")) self.ts.markFinal(name == name_exp, f"{name} and {name_exp} match") @allure.step("Apple playlist page - popup get days count from day picker") def popup_get_days_count_from_day_picker(self): start_t = self.get_text(*self.locator(self.apple_playlist_page, "popup_day_picker")).split("–")[0] end_t = self.get_text(*self.locator(self.apple_playlist_page, "popup_day_picker")).split("–")[1] start = datetime.datetime.strptime(start_t, self.trackPage.get_date_format_from_locale()).date() end = datetime.datetime.strptime(end_t, self.trackPage.get_date_format_from_locale()).date() days_count_exp = (end - start).days + 1 return days_count_exp @allure.step("Apple playlist page - popup get start and date from day picker") def popup_get_start_end_date(self): start_t = self.get_text(*self.locator(self.apple_playlist_page, "popup_day_picker")).split("–")[0] end_t = self.get_text(*self.locator(self.apple_playlist_page, "popup_day_picker")).split("–")[1] start = datetime.datetime.strptime(start_t, self.trackPage.get_date_format_from_locale()).date() end = datetime.datetime.strptime(end_t, self.trackPage.get_date_format_from_locale()).date() return {"start": start, "end": end} @allure.step("Apple playlist page - popup get days in playlist") def popup_get_days_in_playlist(self): days_ui = int(self.get_text(*self.locator(self.apple_playlist_page, "popup_day_count")).split(" ")[0]) return days_ui @allure.step("Apple playlist page - popup days in playlist is present") def popup_get_days_in_playlist_is_displayed(self): days_ui = self.is_element_displayed(*self.locator(self.apple_playlist_page, "popup_day_count")) return days_ui @allure.step("Apple playlist page - popup verify date picker, days in playlist and hint") def pop_verify_date_picker(self): days_count_exp = self.popup_get_days_count_from_day_picker() days_ui = self.popup_get_days_in_playlist() days = days_count_exp % 7 weeks = days_count_exp // 7 loc = f"{weeks} weeks and {days} day" if days == 0: loc = f"{weeks} weeks" elif days > 1: loc = f"{loc}s" days_in_playlist = self.get_element(*self.locator(self.apple_playlist_page, "popup_day_count")) ActionChains(self.driver).move_to_element(to_element=days_in_playlist).perform() tooltip = self.is_element_displayed(locator=f"//*[text()='{loc}']", locator_type="xpath") end = self.popup_get_start_end_date()["end"] self.ts.markFinal(end == datetime.date.today(), f"end date: {end} is correct: {datetime.date.today()}") self.ts.markFinal( days_count_exp == days_ui or days_count_exp == days_ui + 1, f"expected: {days_count_exp} and ui: {days_ui} match", ) self.ts.markFinal(tooltip, "hint with days is correct") self.click_element(*self.locator(self.apple_playlist_page, "popup_day_picker")) self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "popup_day_picker_last_date")) day_of_month = int(self.get_text(*self.locator(self.apple_playlist_page, "popup_day_picker_last_date"))) color = self.get_element(*self.locator(self.apple_playlist_page, "popup_day_picker_last_date")).value_of_css_property("background-color") for p in self.dp_predefined_periods: period = self.is_element_displayed(locator=f"//*[contains(@id, '-modal-window-day-picker-{p}')]", locator_type="xpath") self.ts.markFinal(period, f"{p} period is displayed") current_day = int(datetime.date.today().strftime("%d")) ran = list(range(current_day - 1, current_day + 1)) self.ts.markFinal(day_of_month in ran, f"day of month: {day_of_month}, expected: {ran}") self.ts.markFinal(color == "rgba(0, 0, 0, 1)", f"color: {color}") self.click_element(*self.locator(self.apple_playlist_page, "popup_day_picker")) @allure.step("Apple playlist page - popup choose predefined period and verify") def popup_verify_predefined_periods(self): for p, d in zip(self.dp_predefined_periods, self.dp_predefined_count_days): days_in_playlist_before = self.popup_get_days_in_playlist() xaxis_el = self.get_elements(*self.locator(self.apple_playlist_page, "popup_xaxis")) xaxis_before = [self.get_text(element=e) for e in xaxis_el] kpis_before = [ self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")), self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")), ] self.click_element(*self.locator(self.apple_playlist_page, "popup_day_picker")) self.click_element(locator=f"//*[contains(@id, '-modal-window-day-picker-{p}')]", locator_type="xpath") days_in_playlist_after = self.popup_get_days_in_playlist() count_days = self.popup_get_days_count_from_day_picker() xaxis_el = self.get_elements(*self.locator(self.apple_playlist_page, "popup_xaxis")) xaxis_after = [self.get_text(element=e) for e in xaxis_el] kpis_after = [ self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")), self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")), ] self.ts.markFinal( days_in_playlist_before == days_in_playlist_after, f"days before: {days_in_playlist_before} and after: {days_in_playlist_after} match", ) self.ts.markFinal(count_days >= d, f"count: {count_days} match expected: {d}") self.ts.markFinal(xaxis_before != xaxis_after, f"xaxis: {xaxis_before} is changed for {p}: {xaxis_after}") if d not in [ self.dp_predefined_count_days[2], self.dp_predefined_count_days[3], self.dp_predefined_count_days[4], self.dp_predefined_count_days[5], ]: self.ts.markFinal(kpis_before != kpis_after, f"{kpis_before} is changed to {kpis_after}") @allure.step("Apple playlist page - popup select previous month period") def popup_select_previous_mounth_period(self): kpis_before = [ self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")), self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")), ] self.click_element(*self.locator(self.apple_playlist_page, "popup_day_picker")) previous_month_picker = "DayPicker-NavButton--prev" self.driver.execute_script("document.getElementsByClassName('" + previous_month_picker + "')[0].click();") self.click_element(*self.locator(self.apple_playlist_page, "firstDayOfPreviousMonth")) self.click_element(*self.locator(self.apple_playlist_page, "lastDayOfPreviousMonth")) kpis_after = [ self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")), self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")), ] graph = self.is_element_displayed(*self.locator(self.apple_playlist_page, "popup_day_count")) self.ts.markFinal(kpis_before != kpis_after, f"{kpis_before} is changed to {kpis_after}") self.ts.markFinal(graph, "graph is displayed") @allure.step("Apple playlist page - popup export to csv and verify") def popup_export_to_csv_and_verify(self, tp=False): self.click_element(*self.locator(self.apple_playlist_page, "popup_export_button")) metadata = self.popup_get_metadata() track_name = metadata["track"] playlist_name = self.popup_get_playlist_name() file_path = f"""http://{CoreConfig.SELENOID_HOST}:4444/download/{self.driver.session_id}/Playlist Position - {track_name} - {playlist_name.replace(':', '_')}.csv""" self.log.info(f"file path: {file_path}") columns = [ "Artists", "Track Name", "Track URI", "Playlist Name", "Playlist URI", "Position", "Tracks in Playlist", "Worldwide Streams", "Market Streams", ] data = self.trackPage.read_from_csv(file_path) file = {} for c in columns: file[c] = data.get(c).to_list() self.log.info(f"file: {file}") artist = metadata["artist"] if tp: file_uri = set(file["Track URI"]).pop().split(":")[-1] track_uri = self.get_attribute_value(*self.locator(self.apple_playlist_page, "popup_track_name"), attribute="href").split("/")[-1] self.ts.markFinal(file_uri == track_uri, f"Track URI {file_uri} and {track_uri} match") else: track_uri = int(self.get_attribute_value(*self.locator(self.apple_playlist_page, "popup_track_name"), attribute="href").split("/")[-1]) self.ts.markFinal( list(set(file["Track URI"]))[0] == track_uri, f"Track URI {set(file['Track URI'])} and {track_uri} match", ) playlist_uri = self.get_attribute_value(*self.locator(self.apple_playlist_page, "popup_playlist_name"), attribute="href").split("/")[-1].split("?")[0] ww_streams = int(self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")).replace(",", "")) market_streams = int(self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")).replace(",", "").replace("N/A", "0")) assert_that(set(file["Artists"]).pop()).is_equal_to(str(artist).replace(", ", ",")) self.ts.markFinal( set(file["Track Name"]).pop() == track_name, f"Track Name {set(file['Track Name']).pop()} and {track_name} match", ) self.ts.markFinal( set(file["Playlist Name"]).pop() == playlist_name, f"Playlist Name {set(file['Playlist Name']).pop()} and {playlist_name} match", ) self.ts.markFinal( set(file["Playlist URI"]).pop() == playlist_uri, f"Playlist URI {set(file['Playlist URI']).pop()} and {playlist_uri} match", ) ww_streams_file = sum(f for f in file["Worldwide Streams"] if not math.isnan(f)) market_streams_file = sum(f for f in file["Market Streams"] if not math.isnan(f)) self.ts.markFinal(market_streams_file == market_streams, f"Market Streams {market_streams_file} and {market_streams} match") self.ts.markFinal(ww_streams_file == ww_streams, f"Worldwide Streams {ww_streams_file} and {ww_streams} match") return {"global": file["Worldwide Streams"], "local": file["Market Streams"], "position": file["Position"]} @allure.step("Apple playlist page - popup verify chart tooltip") def verify_chart_tooltip(self, market): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "popup_chart_border")) param = self.popup_get_days_count_from_day_picker() * 2 e = self.get_element(*self.locator(self.apple_playlist_page, "popup_chart_border")) height = int(e.size["height"]) width = int(e.size["width"]) + 1 self.log.info(f"height: {height}, width: {width}") step = int(width / param) self.log.info(f"step: {step}") tooltips = [] global_values = [] local_values = [] percentage = [] positions = [] for t in range(0, width, step): e = self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "popup_chart_border")) ActionChains(self.driver).move_to_element_with_offset(to_element=e, xoffset=t, yoffset=height).perform() tooltip_el = self.get_element(*self.locator(self.apple_playlist_page, "tooltip")) if tooltip_el not in [None, "None", ["None"], [None]]: tooltips.append(self.get_text(element=tooltip_el).strip()) values_tooltip_el = self.get_elements(*self.locator(self.apple_playlist_page, "tooltip_values")) tooltip_values = [self.get_text(element=v).replace(",", "") for v in values_tooltip_el] position_value = int(tooltip_values[0].split(" ")[0]) positions.append(position_value) global_values.append(int(tooltip_values[1])) local_values.append(int(tooltip_values[2].split(" ")[0])) percentage.append(int(tooltip_values[2].split("(")[1].split("%")[0])) self.log.info("tooltip text: {}".format(self.get_text(element=tooltip_el))) self.log.info("popup chart tooltip content: {}".format(tooltips)) self.ts.markFinal( any(self.TOOLTIP_POSITION and self.TOOLTIP_GLOBAL and self.TOOLTIP_MARKET.format(market.upper()) in tool for tool in tooltips), f"tooltip contains all elements: {tooltips}", ) return {"global": global_values, "local": local_values, "percentage": percentage, "position": positions} @allure.step("Apple playlist page - popup verify chart tooltips min/max") def popup_verify_chart_min_max(self, tooltips, market): tooltip_market = self.TOOLTIP_MARKET.format(market.upper()) for c, v in zip(self.dots_colors, [self.TOOLTIP_POSITION, self.TOOLTIP_GLOBAL, tooltip_market]): dots = self.get_elements(locator=f"//*[@fill='rgba({c})'][position() < last()]", locator_type="xpath") self.ts.markFinal(len(dots) > 0, f"count of min/peak dots is: {len(dots)}") if len(dots) > 0: for d in dots: ActionChains(self.driver).move_to_element(to_element=d).perform() tooltip_el = self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "tooltip")) text = self.get_text(element=tooltip_el) self.log.info(f"Tooltip text: {text}") if len(text) > 0: values_tooltip_el = self.get_elements(*self.locator(self.apple_playlist_page, "tooltip_values")) tooltip_values = [self.get_text(element=v).replace(",", "") for v in values_tooltip_el] position_value = int(tooltip_values[0].split(" ")[0]) global_value = int(tooltip_values[1]) market_value = int(tooltip_values[2].split(" ")[0]) self.ts.markFinal( f"{v}\n{self.TOOLTIP_MINIMUM}" or f"{v}\n{self.TOOLTIP_PEAK}" in text, f"tooltip text: \n{v}\n{self.TOOLTIP_MINIMUM} or \n{v}\n{self.TOOLTIP_PEAK} in \n{text}", ) if f"{self.TOOLTIP_POSITION}\n{self.TOOLTIP_PEAK}" in text: ran = list(range(min(tooltips["position"]) - 2, min(tooltips["position"]) + 2)) self.ts.markFinal(position_value in ran, f"peak position is: {position_value}\nexpected: {ran}") elif f"{self.TOOLTIP_POSITION}\n{self.TOOLTIP_MINIMUM}" in text: ran = list(range(max(tooltips["position"]) - 2, max(tooltips["position"]) + 2)) self.ts.markFinal(position_value in ran, f"minimum position is: {position_value}\nexpected: {ran}") elif f"{self.TOOLTIP_GLOBAL}\n{self.TOOLTIP_PEAK}" in text: self.ts.markFinal( global_value == max(tooltips["global"]), f"peak global is: {global_value}\nexpected: {max(tooltips['global'])}", ) elif f"{self.TOOLTIP_GLOBAL}\n{self.TOOLTIP_MINIMUM}" in text: self.ts.markFinal( global_value == min(tooltips["global"]), f"minimum global is: {global_value}\nexpected: {min(tooltips['global'])}", ) elif f"{tooltip_market}\n{self.TOOLTIP_PEAK}" in text: self.ts.markFinal( market_value == max(tooltips["local"]), f"peak local is: {market_value}\nexpected: {max(tooltips['local'])}", ) elif f"{tooltip_market}\n{self.TOOLTIP_MINIMUM}" in text: self.ts.markFinal( market_value == min(tooltips["local"]), f"minimum local is: {market_value}\nexpected: {min(tooltips['local'])}", ) @allure.step("Apple playlist page - popup verify local market") def popup_verify_local_market(self, param): titles = self.get_elements(*self.locator(self.apple_playlist_page, "tooltip_titles")) market = self.get_text(element=titles[1]) self.ts.markFinal(market == f"{param} STREAMS IN PLAYLIST", f"market is: {market}\nexpected: {param}") @allure.step("Apple playlist page - popup verify market in network") def verify_popup_network_market(self, market, isrc, playlist_id): self.page_has_loaded() time.sleep(15) network = self.driver.get_log("performance") result_list = [] for entry in network: log = json.loads(entry["message"])["message"] if log["method"] == "Network.requestWillBeSent" and ("/applemusic/playlists/trackpositionchange" in log["params"]["documentURL"]): result_list.append(log["params"]["documentURL"]) elif log["method"] == "Network.requestWillBeSent" and (f"/apple-consumer-analytics/track-in-container?isrc={isrc}&containerId={playlist_id}" in log["params"]["documentURL"]): result_list.append(log["params"]["documentURL"]) self.log.info(f"Endpoints list: {result_list}") for endpoint in result_list: assert_that(endpoint).contains(playlist_id) assert_that(endpoint).contains(market) @allure.step("Apple playlist page - popup verify market in network") def popup_verify_na(self, market): self.trackPage.select_today_period() self.page_has_loaded() time.sleep(2) ww_streams = self.get_text(*self.locator(self.apple_playlist_page, "popup_global_value")) market_streams = self.get_text(*self.locator(self.apple_playlist_page, "popup_local_value")) self.ts.markFinal("N/A" == ww_streams and market_streams, f"{market_streams} and {ww_streams} are na") param = 2 e = self.get_element(*self.locator(self.apple_playlist_page, "popup_chart_border")) height = int(e.size["height"]) width = int(e.size["width"]) + 1 self.log.info(f"height: {height}, width: {width}") step = int(width / param) self.log.info(f"step: {step}") tooltips = [] for t in range(0, width, step): e = self.get_element(*self.locator(self.apple_playlist_page, "popup_chart_border")) ActionChains(self.driver).move_to_element_with_offset(to_element=e, xoffset=t, yoffset=height).perform() tooltip_el = self.get_element(*self.locator(self.apple_playlist_page, "tooltip")) if tooltip_el not in [None, "None", ["None"], [None]]: tooltips.append(self.get_text(element=tooltip_el).strip()) self.ts.markFinal(len(tooltips) > 0, f"count of tooltips: {len(tooltips)}") self.ts.markFinal(self.TOOLTIP_POSITION in tooltips[0], f"positions is in tooltip: {tooltips[0]}") self.ts.markFinal( self.TOOLTIP_GLOBAL and self.TOOLTIP_MARKET.format(market.upper()) not in tooltips[0], f"global and local market info is not in tooltip: {tooltips[0]}", ) @allure.step("Apple playlist page - popup choose previoud period and verify no data") def popup_verify_no_data_for_previous_period(self): days = self.popup_get_days_in_playlist() count_months = int(days / 30 + 10) self.log.info(f"count of months: {count_months}") self.click_element(*self.locator(self.apple_playlist_page, "popup_day_picker")) for i in list(range(count_months)): button = self.get_element(*self.locator(self.apple_playlist_page, "popup_nav_button_back")) self.click_on_element_js(element=button) self.popup_select_previous_mounth_period() self.popup_verify_no_data() @allure.step("Apple playlist page - popup verify no data") def popup_verify_no_data(self): no_data = self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "popup_no_data")) self.verify_export_button_active(active=False, button="popup_export_button") self.ts.markFinal(self.is_element_displayed(element=no_data), "no data in popup") @allure.step("Apple playlist page - open apple playlist on apple portal and verify") def open_playlist_on_apple_and_verify(self, id, market): self.click_element(*self.locator(self.apple_playlist_page, "apple_playlist_icon")) self.comparison_page.switch_to_tab(2) url_apple = self.get_url() self.ts.markFinal( url_apple == f"https://music.apple.com/{market}/playlist/{id}", f"apple playlist url on apple portal: {url_apple}", ) @allure.step("Apple Playlist title is present") def title_is_present(self): self.wait_for_element_visible(*self.locator(self.apple_playlist_page, "playlist_name")) title = self.is_element_displayed(*self.locator(self.apple_playlist_page, "playlist_name")) assert_that(title).is_true() @allure.step("Apple Playlist - get tracks id from the Tracklist") def get_tracks_id_from_tracklist(self): loc = "//*[contains(@href, '/track/')]" tracks_id = [] self.wait_for_element_visible(locator=loc, locator_type="xpath") elms = self.get_elements(locator=loc, locator_type="xpath") for e in elms: tracks_id.append(str(self.get_attribute_value(element=e, attribute="href")).split("/")[-1]) self.log.info(f"tracks id from the Tracklist: {tracks_id}") return tracks_id