import datetime import logging import time import allure from assertpy import assert_that from selenium.webdriver import ActionChains from ui_automation_framework.core import BasePage, TestStatus from ui_automation_framework.utils import 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.login_page import LoginPage 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 AmazonPlaylistPage(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, 'amazon-playlist-table-table-cell-{column}-')]" track_names_only_locator = "amazon-playlist-table-table-cell-track-name" artist_names_only_locator = "//*[contains(@id, 'amazon-playlist-table-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"] amazon_playlist_title = "amazon-playlist-title" export_button = "//button[.='Export']" def __init__(self, driver): super().__init__(driver) self.driver = driver self.loginPage = LoginPage(self.driver) self.amazon_playlist_page = self.get_page_locators("AmazonPlaylistPage", "amazon_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 amazon playlist page") def open_amazon_playlist_page(self, id, verify=True): self.driver.get(f"{CoreConfig.ENV_BASE_URL}/amazon/playlist/{id}") if verify: self.is_opened() @allure.step("Amazon plaaylist page - is opened") def is_opened(self): assert_that(self.is_element_displayed(self.amazon_playlist_title)).is_true() @allure.step("Amazon playlist page - donuts are displayed") def are_donuts_displayed(self): self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "donut_charts")) donuts = self.get_elements(*self.locator(self.amazon_playlist_page, "donut_charts")) self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "donut_text_frontline")) frontline = self.is_element_displayed(*self.locator(self.amazon_playlist_page, "donut_text_frontline")) self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "donut_text_local")) local = self.is_element_displayed(*self.locator(self.amazon_playlist_page, "donut_text_local")) self.ts.markFinal(len(donuts) == 2, "2 donuts are displayed") self.ts.markFinal(frontline == local == True, "donuts and texts for donuts are displayed") @allure.step("Amazon playlist page - calculate frontline tracks percentage") def get_frontline_tracks_percentage_api(self, id, country): resp = self.api_client.get_amazon_tracklist(id=id, country=country)["items"] dates = [] for id in resp: if "release_date" in id["track"] and id["track"]["release_date"] is not None: dates.append(datetime.datetime.strptime(id["track"]["release_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(resp)) * 100) self.log.info("percentage: {}".format(percentage)) return percentage def get_percentage_ui(self): self.scroll_to_element(*self.locator(self.amazon_playlist_page, "percentage")) self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "percentage")) self.page_has_loaded() time.sleep(3) elements = self.get_elements(*self.locator(self.amazon_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("Amazon playlist page - get percentage ui frontline") def get_percentage_frontline_ui(self): return self.get_percentage_ui()[0] @allure.step("Amazon playlist page - get percentage ui local") def get_percentage_local_ui(self): return self.get_percentage_ui()[1] @allure.step("Amazon playlist page - calculate local tracks percentage") def get_local_tracks_percentage_api(self, id, country): resp = self.api_client.get_amazon_tracklist(id=id, country=country)["items"] 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(f'{id} {country} local isrc" {local_isrcs}') percentage = int((len(local_isrcs) / len(isrcs_all)) * 100) self.log.info(f"{id} {country} percentage: {percentage}") return percentage @allure.step("Amazon playlist page - get selected market") def get_selected_market(self): element = self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "market_switcher")) return str(self.get_text(element=element)) @allure.step("Amazon playlist page - change market") def change_market(self, name): self.wait_for_element_visible(*self.locator(self.amazon_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"Amazon 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("Amazon playlist page - verify info icon") def verify_info_icon(self, id): icon = self.wait_for_element_visible(*self.locator(self.amazon_playlist_page, "info_icon")) ActionChains(self.driver).move_to_element(to_element=icon).perform() info_icon_tooltip = self.get_text(*self.locator(self.amazon_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 last received: {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("Amazon 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.amazon_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("Amazon playlist page - click on updated info") def click_on_info_updated(self): self.click_element(*self.locator(self.amazon_playlist_page, "info_updated")) @allure.step("Amazon playlist page - verify icon time") def verify_icon_time(self, id, market): icon_time = self.get_element(*self.locator(self.amazon_playlist_page, "icon_time")) date_text = self.get_text("//*[contains(text(), 'Updated ')]", "xpath") 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 = "Playlist data last received: " date_api = self.api_client.get_amazon_tracklist(id=id, country=market)["items"][0]["latest_position_date"] date_api = datetime.datetime.strptime(date_api, "%Y-%m-%d").date() today_date = datetime.date.today() if today_date == date_api: updated_when = "24 hours ago" elif (today_date - date_api).days == 1: updated_when = "yesterday" else: updated_when = f"{(today_date - date_api).days} days ago" date_api = datetime.datetime.strptime(str(date_api), "%Y-%m-%d").strftime(self.trackPage.get_date_format_from_locale()) assert_that(f"{tooltip_start}{date_api}.").is_equal_to(icon_time_tooltip) assert_that(date_text).is_equal_to(f"Updated {updated_when}") @allure.step("Amazon playlist page - open market droplist") def market_droplist_click(self): self.page_has_loaded() self.scroll_to_element(*self.locator(self.amazon_playlist_page, "market_switcher")) self.wait_for_element_clickable(*self.locator(self.amazon_playlist_page, "market_switcher")) self.click_element(*self.locator(self.amazon_playlist_page, "market_switcher")) self.page_has_loaded() def wait_ap_is_loaded(self): self.wait_for_element_clickable(*self.locator(self.amazon_playlist_page, "button_export")) @allure.step("Amazon playlist page - verify page elements") def verify_elements(self): locs = [ "//*[contains(@class, 'icon-amazon')]/following-sibling::*[text()='PLAYLIST']", "//img[contains(@src, 'amazon')]", "//*[@id='amazon-playlist-subtitle-owner-name']", "//*[@id='amazon-playlist-market-dd']", "//*[contains(text(), 'Tracklist (')]", "//*[text()='Tracklist']/following-sibling::*/span", "//*[@id='amazon-playlist-filter-input']", "//*[contains(@class, 'icon-export')]", "//*[contains(@class, 'ReactVirtualized__List')]", "//a[contains(@href, 'https://music.amazon.com/playlists/')]/*[contains(@class, 'icon-amazon')]", ] for loc in locs: assert_that(self.is_element_displayed(loc, "xpath")).described_as(loc).is_true() @allure.step("Amazon playlist page - get market dd flags") def get_market_dd_flags_ui(self): loc_flags = "//*[contains(@id, 'market') and contains(@id, 'flag')]/img" loc_names = "//*[contains(@id, 'market') and contains(@id, 'label')]" self.wait_for_element_visible(loc_flags, "xpath") flags_els = self.get_elements(loc_flags, "xpath") flags = [f.get_attribute("src").split("/")[-1].split(".")[0] for f in flags_els] names_els = self.get_elements(loc_names, "xpath") names = [self.get_text(element=n) for n in names_els] return {"flags": flags, "names": names} @allure.step("Amazon playlist page - market dd filter") def market_dd_filter_by(self, param): loc = "//*[contains(@id, 'market-dd-filter-input')]" filter_el = self.wait_for_element_clickable(loc, "xpath") self.send_text(data=param, element=filter_el) @allure.step("Amazon playlist page - market dd clear icon click") def market_dd_clear_filter(self): loc = "amazon-playlist-market-dd-filter-input-close-icon" icon = self.wait_for_element_clickable(loc) self.click_element(element=icon) @allure.step("Amazon playlist page - market dd verify no markets") def verify_no_markets(self): loc = "//*[text()='No markets found.']" assert_that(self.is_element_displayed(loc, "xpath")).is_true() @allure.step("Amazon playlist page - get metadata - UI") def get_metadata(self): art_link_loc = "//img[contains(@src, 'amazon')]" title_loc = self.amazon_playlist_title category_loc = "amazon-playlist-subtitle-owner-name" art_link = self.get_attribute_value(element=self.wait_for_element_clickable(art_link_loc, "xpath"), attribute="src") title = self.get_text(title_loc) category = self.get_text(category_loc) return {"art_link": art_link, "title": title, "category": category} @allure.step("Amazon playlist page - click on title") def click_on_title(self): title_loc = self.amazon_playlist_title title_el = self.wait_for_element_visible(title_loc) self.click_element(element=title_el) @allure.step("Amazon playlist page - get tracklist count") def get_tracklist_count(self): loc = "//*[contains(text(), 'Tracklist (')]" el = self.wait_for_element_visible(loc, "xpath") count = int(self.get_text(element=el).split("(")[-1].split(")")[0]) return count @allure.step("Amazon playlist page - get last position") def get_last_position(self): loc = "(//*[contains(@id, 'cell-chart-position-')])[last()]" time.sleep(1) self.scroll_to_element(loc, "xpath") time.sleep(1) self.scroll_to_element(loc, "xpath") time.sleep(1) self.log.info("Last position: " + str(int(self.get_text(loc, "xpath")))) return int(self.get_text(loc, "xpath")) @allure.step("Amazon playlist page - get tracklist state") def get_tracklist_state(self): loc = "//*[text()='Tracklist']/following-sibling::*/span[string-length(text()) > 0]" state = self.get_text(loc, "xpath").split(",")[0] return state @allure.step("Amazon playlist page - click on tracklist") def tracklist_click(self): loc = "//*[text()='Tracklist']/following-sibling::*/span[string-length(text()) > 0]" el = self.wait_for_element_clickable(loc, "xpath") self.click_element(element=el) @allure.step("Amazon playlist page - verify tracklist initial date") def tl_verify_dates_dd(self, market=""): dates_from_dd = self.get_elements("//div[text()='Tracklist']/following-sibling::*/..//*[contains(text(), '/')]", "xpath") id = self.get_url().split("/")[-1].split("?")[0] if market == "": market = self.trackPage.parameter_from_url("hd_filter_market") start = "2022-01-01" end = self.api_client.get_latest_date_all()["amazon"] api_resp = self.api_client.get_amazon_tracklist_start_end_id_market(id, start, end, market)["items"] 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") dates_from_dd = [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 dates_from_dd] dates_api = sorted(list(set(datetime.datetime.strptime(t["date"], "%Y-%m-%d").date() for t in api_resp)), reverse=True) assert_that(dates_ui).is_equal_to(dates_api) assert_that(color_before).is_not_equal_to(color_after) @allure.step("Amazon playlist page - change date") def tl_change_date(self, param): button_loc = "//div[text()='Tracklist']/following-sibling::*" dates_loc = f"{button_loc}/..//*[contains(text(), '/')]" self.click_element(button_loc, "xpath") dates_from_dd = self.get_elements(dates_loc, "xpath") self.click_on_element_js(element=dates_from_dd[param]) return self.get_text(element=dates_from_dd[param]).split(",")[0] @allure.step("Amazon playlist page - verify table columns") def scroll_to_tracklist(self): self.scroll_to_element("//*[@id='amazon-playlist-table-header']/*[@id]", "xpath") @allure.step("Amazon playlist page - verify table columns") def verify_table_columns(self, date="Current"): self.scroll_to_tracklist() self.wait_ap_is_loaded() loc = "amazon-playlist-table-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, ] 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, "C", "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) assert_that(column_names).is_equal_to(names_expected) @allure.step("Amazon playlist page - tl get all available dates") def tl_get_all_dates(self): dates_from_dd = self.get_elements("//*[text()='Tracklist']/following-sibling::*/..//*[contains(text(), '/')]", "xpath") dates = [self.get_text(element=d) for d in dates_from_dd] return dates @allure.step("Amazon playlist page - filter_table") def filter_table(self, param, clean_up=False): loc = "amazon-playlist-filter-input" if clean_up: self.click_filter_clear_icon() el = self.wait_for_element_clickable(loc) self.send_text(data=param, element=el) @allure.step("Amazon playlist page - sort table by column") def sort_table_by_column(self, param): loc = f"amazon-playlist-table-table-cell-{param}" el = self.wait_for_element_clickable(loc) self.click_element(element=el) @allure.step("Amazon playlist page - verify filter input placeholder and focus") def filter_verify_placeholder_and_focus(self): loc = "amazon-playlist-filter-input" el = self.wait_for_element_clickable(loc) text = "Filter" attr = "placeholder" focused_el = self.driver.switch_to.active_element assert_that(focused_el).is_not_equal_to(el) placeholder = self.get_attribute_value(element=el, attribute=attr) assert_that(placeholder).is_equal_to(text) self.click_element(element=el) el = self.wait_for_element_clickable(loc) placeholder = self.get_attribute_value(element=el, attribute=attr) color = el.value_of_css_property("border-color") assert_that(placeholder).is_equal_to(text) assert_that(color).is_equal_to("rgb(1, 156, 254)") @allure.step("Amazon playlist page - get table track names") def get_table_track_and_artists_names(self): loc_track = "//*[@id='amazon-playlist-table-table-cell-track-name']/a" loc_artist = "//*[@id='amazon-playlist-table-table-cell-name'][string-length(.) > 0]" time.sleep(0.5) self.wait_for_element_visible(loc_track, "xpath") els_tracks = self.get_elements(loc_track, "xpath") self.wait_for_element_visible(loc_artist, "xpath") els_artists = self.get_elements(loc_artist, "xpath") tracks = [self.get_text(element=e) for e in els_tracks] artists = [self.get_text(element=e) for e in els_artists] len_min = min(len(tracks), len(artists)) self.log.info(f"tracks names: {tracks}") self.log.info(f"artists names: {artists}") track_and_artists = [] for t, a in zip(tracks[:len_min], artists[:len_min]): track_and_artists.append(f"{t}\n{a}") self.log.info(f"track and artists names: {track_and_artists}") return track_and_artists @allure.step("Amazon playlist page - get filter input text") def get_filter_input_text(self): loc = "amazon-playlist-filter-input" text = self.get_attribute_value(locator=loc, locator_type="id", attribute="value") return text @allure.step("Amazon playlist page - click filter clear icon") def click_filter_clear_icon(self): icon_loc = "amazon-playlist-filter-input-close-icon" icon = self.get_element(icon_loc) self.click_on_element_js(element=icon) @allure.step("Amazon playlist page - verify no results") def verify_no_results(self): loc = "//*[@id='amazon-playlist-table']//../*[text()='No results to show.']" assert_that(self.is_element_displayed(loc, "xpath")).is_true() @allure.step("Amazon playlist page - open popup") def open_popup(self, popup=1): loc = f"(//*[contains(@id, 'chart-position-')])[{popup}]" loc_popup_title = "amazon-playlisttrack-in-playlist-modal-window-title" icon = self.wait_for_element_clickable(loc, "xpath") self.click_element(element=icon) assert_that(self.is_element_displayed(loc_popup_title)).is_true() @allure.step("Amazon playlist page - click on element") def click_on_name(self, element): loc = f"amazon-playlisttrack-in-playlist-modal-window-{element}-link" self.click_element(loc) @allure.step("Amazon playlist page - close popup") def close(self): loc = "amazon-playlisttrack-in-playlist-modal-window-close-icon" icon = self.wait_for_element_clickable(loc) color_before = icon.value_of_css_property("background-color") self.hover_on_element(element=icon) color_after = icon.value_of_css_property("background-color") cursor = icon.value_of_css_property("cursor") assert_that(cursor).is_equal_to("pointer") assert_that(color_before).is_not_equal_to(color_after) self.click_element(element=icon) self.is_opened() @allure.step("Amazon playlist page - verify export hover") def verify_export_hover(self): export = self.wait_for_element_clickable(self.export_button, "xpath") 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_before).is_not_equal_to(color_after) @allure.step("Amazon playlist page - verify export") def verify_export(self, date=""): export = self.wait_for_element_clickable(self.export_button, "xpath") self.click_element(element=export) playlist_name = self.trackPage.get_track_title(True) file_path = f"""http://{CoreConfig.SELENOID_HOST}:4444/download/{self.driver.session_id}/Analyze Playlist - {playlist_name}.csv""" columns = [position, market, artist, track, release_date, track_uri, isrc, in_playlist_days, global_streams7_days, global_streams7_avg_days, market_streams7_days, market_streams_avg7_days] = [ "Position", "Market", "Artist", "Track", "Release Date", "Track URI", "ISRC", "In Playlist Days", "Global Streams, 7 Days", "Global Streams Avg, 7 Days", "Market Streams, 7 Days", "Market Streams Avg, 7 Days", ] if date != "": columns = [position, market, artist, track, release_date, track_uri, isrc, global_streams7_avg_days, market_streams7_days] = ["Position", "Market", "Artist", "Track", "Release Date", "Track URI", "ISRC", "Global Streams", "Market Streams"] data = self.trackPage.read_from_csv(file_path) self.log.info(f"pandas data: {data}") file = {} for c in list(data.columns): file[c] = data.get(c).to_list() self.log.info(f"file: {file}") assert_that(list(data.columns)).is_equal_to(columns) assert_that(file[position]).is_sorted() position_ui = self.get_table_column_values("position") countries_ui = set(c.upper() for c in self.get_table_column_values("country")) tracks_ui = self.get_table_column_values("track-name") artists_ui = self.get_table_column_values("name") dates_ui = self.get_table_column_values("date") streams_average_ui = [s for s in self.get_table_column_values("streams-average") if s > 0] countries_file = [str(f).replace("nan", "GULF") for f in file[market]] assert_that(position_ui).is_subset_of(file[position]) assert_that(countries_ui).is_subset_of(countries_file) assert_that(tracks_ui).is_subset_of(file[track]) assert_that(artists_ui).is_subset_of(file[artist]) assert_that(dates_ui).is_subset_of(file[release_date]) assert_that(streams_average_ui).is_subset_of(file[global_streams7_avg_days]) if date == "": days_in_playlist_ui = self.get_table_column_values("days-in-playlist") assert_that(days_in_playlist_ui).is_subset_of(file[in_playlist_days]) @allure.step("Amazon playlist page - get table column values") def get_table_column_values(self, param): loc = f"//*[contains(@id, 'amazon-playlist-table-table-cell-{param}-')]" if param == "position": loc = "//*[contains(@id, 'amazon-playlist-table-table-cell-position-') and not(contains(@id, 'change'))]" elif param == "country": loc = f"//*[contains(@id, 'amazon-playlist-table-table-cell-{param}-')]//../img" elif param in ["name", "track-name", "date"]: loc = f"//*[@id='amazon-playlist-table-table-cell-{param}']" elif param == "track_id": loc = "//*[contains(@href, '/track/')]" els = self.get_elements(loc, "xpath") values = [self.get_text(element=e) for e in els] if param in ["position", "position-change", "days-in-playlist", "streams-average"]: values = [int(v.replace(",", "")) if len(v) > 0 else 0 for v in values] elif param == "country": values = [c.get_attribute("src").split("/")[-1].split(".")[0].replace("_unknown", "gulf") for c in els] elif param == "date": values = [v for v in values if v != "N/A"] elif param == "track_id": values = [self.get_attribute_value(element=i, attribute="href").split("/")[-1] for i in els] self.log.info(f"column: {param}: {values}") return values @allure.step("Amazon playlist page - verify export button inactive") def verify_export_inactive(self, inactive=True): export = self.wait_for_element_clickable(self.export_button, "xpath") color = export.value_of_css_property("background-color") if inactive: assert_that(color).is_equal_to("rgba(255, 198, 25, 1)") @allure.step("Amazon playlist page - unstar all tracks") def unstar_all_tracks(self): user = self.loginPage.get_user_email_with_worker() token = self.api_client.authorize(user=user) starred_all = self.get_isrcs_ids_all_starred_tracks() for isrc, id in zip(starred_all["isrcs"], starred_all["ids"]): self.api_client.delete_apple_starred_track(isrc=isrc, id=id, token=token) @allure.step("Amazon playlist page - get all starred tracks isrcs and ids") def get_isrcs_ids_all_starred_tracks(self): user = self.loginPage.get_user_email_with_worker() token = self.api_client.authorize(user=user) starred_all = self.api_client.get_starred_tracks(token=token)["items"] starred_isrc_all = [i["extra_data"]["isrc"] for i in starred_all] starred_id_all = [i["extra_data"]["id"] for i in starred_all] return {"isrcs": starred_isrc_all, "ids": starred_id_all} @allure.step("Amazon playlist page - get all starred tracks isrcs") def get_isrc_for_track_by_index(self, market, index=0): ids_loc = "//*[contains(@id, 'amazon-playlist-table-table-cell-track-name')]/a" tracklist_loc = "//*[text()='Tracklist']" self.scroll_to_element(tracklist_loc, "xpath") self.wait_for_element_clickable(ids_loc, "xpath") ids_els = self.get_elements(ids_loc, "xpath") apple_id = ids_els[index].get_attribute("href").split("/")[-1] 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"] return isrc @allure.step("Amazon playlist page - get all starred tracks isrcs") def star_unstar_by_index_and_verify_ui(self, star=True, index=0): starred_loc = "//*[contains(@class, 'star')]/parent::*[@id]" ids_loc = "//*[contains(@id, 'amazon-playlist-table-table-cell-track-name')]/a" tracklist_loc = "//*[text()='Tracklist']" self.scroll_to_element(tracklist_loc, "xpath") self.wait_for_element_clickable(ids_loc, "xpath") table_loaded_selector = "//*[contains(@id, 'amazon-playlist-table-table-cell-streams-average-')][string-length(.) > 0]" self.wait_for_element_visible(table_loaded_selector, "xpath") self.wait_for_element_visible(locator=starred_loc, locator_type="xpath") starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") color_before = starred_track_icons[index].value_of_css_property("color") self.click_element(element=starred_track_icons[index]) hint_loc_core = "//*[text()='Track successfully {}']" if star: hint_loc = "starred" else: hint_loc = "unstarred" hint = self.wait_for_element_visible(locator=hint_loc_core.format(hint_loc), locator_type="xpath") assert_that(self.is_element_displayed(element=hint)).is_true() ids_els = self.get_elements(ids_loc, "xpath") self.hover_on_element(element=ids_els[0]) starred_track_icons = self.get_elements(locator=starred_loc, locator_type="xpath") color_after = starred_track_icons[index].value_of_css_property("color") assert_that(color_before).is_not_equal_to(color_after) @allure.step("Apple playlist page - track list get column values") def tl_get_column_values(self, column): loc = f"//*[contains(@id, 'amazon-playlist-table-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("//button[.='Export']", "xpath") 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(",", "")) if self.get_text(element=n) != "" else 0 for n in column_el] 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("Amzon playlist page - track list get song ids") def tl_get_song_ids(self): 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] song_positions = [] for v in values: value_position_loc = f"//a[@href='/apple/track/{v}']/ancestor::div[contains(@id, 'amazon-playlist-table-table-cell-track-')]" value_position = self.get_element(locator=value_position_loc, locator_type="xpath") value_position_attr = int(str(self.get_attribute_value(element=value_position, attribute="id")).split("-")[-1]) song_positions.append(value_position_attr) self.log.info(f"song ids: {values}") self.log.info(f"song positions: {song_positions}") return values, song_positions @allure.step("Apple playlist page - tl scroll down and verofy back to top button") def scroll_down_verify_back_button(self): self.scroll_to_tracklist() 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("amazon-playlist-back-to-top") self.verify_table_columns() self.click_element(element=back_button) top_of_page = self.is_element_displayed("//*[contains(@class, 'icon-info')]", "xpath") assert_that(top_of_page).is_true() @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.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=starred_hint), "starred hint is displayed") 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("Amazon playlist page - tl verify country hint") def verify_country_hint(self, index=0): self.scroll_to_tracklist() countries = self.get_elements(locator=self.tl_column_values_locator.format(column=self.TL_COLUMN_COUNTRY), locator_type="xpath") country_code_ui = self.get_table_column_values(self.TL_COLUMN_COUNTRY)[index] ActionChains(self.driver).move_to_element(to_element=countries[index]).perform() country_hint = self.get_text(locator="(//iframe/following-sibling::div/*)[last()]", locator_type="xpath") country_exp = self.sql_client.get_market_name_by_country_code(country_code_ui) assert_that(country_hint).is_equal_to(country_exp) @allure.step("Amazon playlist page - tl verify track name hint") def verify_track_name_hint(self, index=0): self.scroll_to_tracklist() track_names = self.get_elements(locator=self.track_names_only_locator) track_name = self.get_text(element=track_names[index]) ActionChains(self.driver).move_to_element(to_element=track_names[index]).perform() track_hint = self.get_text(locator="(//iframe/following-sibling::div/*)[last()]", locator_type="xpath") assert_that(track_hint).is_equal_to(track_name) @allure.step("Amazon playlist page - tl verify track name link") def verify_track_name_link(self, index=0): self.scroll_to_tracklist() track_name = self.get_elements(locator=self.track_names_only_locator)[index] name = self.get_text(element=track_name) self.log.info(f"Track name: {name}") self.click_element(element=track_name) self.trackPage.is_track_page_title_present(name) @allure.step("Amazon playlist page - tl verify artist name hint") def verify_artist_name_hint(self, index=0): self.scroll_to_tracklist() url_before = self.get_url() artist_el = self.get_elements(locator=self.artist_names_only_locator, locator_type="xpath")[index] self.click_element(element=artist_el) url_after = self.get_url() assert_that(url_before).is_equal_to(url_after) @allure.step("Amazon playlist page - get chosen date") def get_chosen_date(self): loc = "//*[text()='Tracklist']/following-sibling::*/*[1]" date = self.wait_for_element_visible(loc, "xpath") date = self.get_text(element=date) if date != "Current": date = datetime.datetime.strptime(date.split(",")[0], self.trackPage.get_date_format_from_locale()).strftime("%Y-%m-%d") return date