import datetime import logging 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 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.artist_page import ArtistPage from app.src.pages.login_page import LoginPage from app.src.pages.top_charts_page import TopChartsPage from app.src.pages.track_page import TrackPage class ChartDigestPage(BasePage): log = cl.Logger(logging.DEBUG) TOP_VIEW = "top-view" MAJOR_MOVES = "major-moves" CHART_CHANGES = "chart-changes" BUBBLING_UNDER = "bubbling-under" SECTION_TOP_10 = "top-10" SECTION_EXITS_TOP_10 = "exits-from-top-10" TAB_APPLE = "apple" TAB_SPOTIFY = "spotify" gtp_track_name = "track-name" gtp_artist_name = "track-artist-name" el_values = [ gtp_track_name, gtp_artist_name, "hot-hits-title", "streams-value", "streams-title", "hot-hits-title", "chart-position-title", ] main_selector = "gtp-card-" SONY = "sony" NON_SONY = "non_sony" def __init__(self, driver): super().__init__(driver) self.driver = driver self.chart_digest_locators = self.get_page_locators("ChartDigestPage", "chart_digest.json") self.trackPage = TrackPage(self.driver) self.topChartsPage = TopChartsPage(self.driver) self.artist_page = ArtistPage(self.driver) self.api_client = ApiClient() self.sql_client = MySqlClient() self.ts = TestStatus(self.driver) self.loginPage = LoginPage(self.driver) @allure.step("Open Chart Digest page") def open_charts_digest_page(self): self.driver.get(CoreConfig.ENV_BASE_URL) @allure.step("Chart Digest - page is opened") def is_opened(self): self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "most_visited_title")) most_visited = self.is_element_displayed(*self.locator(self.chart_digest_locators, "most_visited_title")) self.ts.markFinal(most_visited, "chart digest is opened") @allure.step("No tracks in recently visited section") def no_most_visited_tracks_are_present(self): return self.is_element_present(*self.locator(self.chart_digest_locators, "dashboard-most-visited-no-tracks")) @allure.step("Track name on the track card") def track_card_get_track_name(self, track): track_name = self.get_text(*self.locator(self.chart_digest_locators, track)) return track_name @allure.step("Number of the track cards") def get_number_for_the_track_cards(self): elements = self.get_elements("a[id^=dashboard-most-visited-card-]", "css") self.log.info(len(elements)) return len(elements) @allure.step("Chart Digest - click table filter icon") def click_filter_icon_table(self, table): filter_el = self.wait_for_element_clickable(locator="dashboard-{}-filter-dd".format(table)) is_displayed = self.is_element_displayed(element=filter_el) self.wait_for_element_visible(locator="dashboard-{}-filter-dd".format(table)) self.wait_for_element_clickable(locator="dashboard-{}-filter-dd".format(table)) self.click_element(element=filter_el) self.ts.markFinal(is_displayed, "filter for table: {} is displayed".format(table)) @allure.step("Chart Digest - verify table filter icon") def verify_filter_window_for_table(self, table, open=True): track_owner_title = self.get_element(locator="//*[@id='dashboard-{}-filter-dd-title'][text()='Track Owner']".format(table), locator_type="xpath") filter_checkbox_non_sony = self.get_element(locator="//*[@id='dashboard-{}-filter-dd-checkbox-non_sony']".format(table), locator_type="xpath") filter_sony_title = self.get_element( locator="//*[@id='dashboard-{}-filter-dd-checkbox-sony']/following-sibling::*[text()='Sony Tracks']".format(table), locator_type="xpath", ) filter_non_sony_title = self.get_element( locator="//*[@id='dashboard-{}-filter-dd-checkbox-non_sony']/following-sibling::*[text()='Non-Sony Tracks']".format(table), locator_type="xpath", ) filter_apply = self.get_element(locator="//*[@id='dashboard-{}-filter-dd']/following::button[contains(@id, 'apply-btn')][1]".format(table), locator_type="xpath") filter_checkbox_sony = self.get_element(locator="//*[@id='dashboard-{}-filter-dd-checkbox-sony']".format(table), locator_type="xpath") if open: elements = [ track_owner_title, filter_sony_title, filter_non_sony_title, filter_apply, filter_checkbox_sony, filter_checkbox_non_sony, ] for e in elements[:-2]: e_displayed = self.is_element_displayed(element=e) self.ts.markFinal(e_displayed, "element: {} is displayed".format(elements.index(e))) for e in elements[-2:]: e_displayed = self.is_element_present(element=e) self.ts.markFinal(e_displayed, "element: {} is present".format(elements.index(e))) else: is_open = self.is_element_displayed(element=track_owner_title) self.ts.markFinal(not is_open, "filter window for table: {} is open".format(table)) @allure.step("Chart Digest - click on page title") def click_on_page_title(self, modal=False): if modal: self.click_element(*self.locator(self.chart_digest_locators, "chart-changes-popup-title")) else: self.click_element(*self.locator(self.chart_digest_locators, "most_visited_title")) @allure.step("Chart Digest - filter table check sony tracks") def filter_check_sony_tracks(self, table, checked=True, apply_filter=True): filter_checkbox_sony = self.get_element(locator="dashboard-{}-filter-dd-checkbox-sony".format(table)) if not self.trackPage.is_checked(locator="dashboard-{}-filter-dd-checkbox-sony".format(table), locator_type="id"): self.click_element(element=filter_checkbox_sony) if self.trackPage.is_checked(locator="dashboard-{}-filter-dd-checkbox-non_sony".format(table), locator_type="id"): self.click_element(locator="dashboard-{}-filter-dd-checkbox-non_sony".format(table)) filter_apply_loc = "//*[@id='dashboard-{}-filter-dd']/following::button[contains(@id, 'apply-btn')][1]".format(table) apply = self.is_enabled(locator=filter_apply_loc, locator_type="xpath") if apply_filter: self.click_element(locator=filter_apply_loc, locator_type="xpath") self.ts.markFinal(apply == checked, "apply is enabled") @allure.step("Chart Digest - top view get names") def get_names_from_table(self, table, modal=False): if table == "chart-changes": sel = "//*[contains(@id, 'dashboard-{}-card-')]/*".format(table) if modal: sel = "//*[contains(@id, 'dashboard-{}-modal-item')]/*".format(table) else: sel = "//*[contains(@id, 'dashboard-{}-table-cell-name-')]".format(table) names_el = self.get_elements(locator=sel, locator_type="xpath") names = [self.get_text(element=n) for n in names_el] return names @allure.step("Chart Digest - filter table check non sony tracks") def filter_check_non_sony_tracks(self, table, checked=True, apply_filter=True): filter_checkbox_non_sony = self.get_element(locator="//*[@id='dashboard-{}-filter-dd-checkbox-non_sony']".format(table), locator_type="xpath") if not self.trackPage.is_checked(locator="dashboard-{}-filter-dd-checkbox-non_sony".format(table), locator_type="id"): self.click_element(element=filter_checkbox_non_sony) if self.trackPage.is_checked(locator="dashboard-{}-filter-dd-checkbox-sony".format(table), locator_type="id"): self.click_element(locator="dashboard-{}-filter-dd-checkbox-sony".format(table)) filter_apply_loc = "//*[@id='dashboard-{}-filter-dd']/following::button[contains(@id, 'apply-btn')][1]".format(table) apply = self.is_enabled(locator=filter_apply_loc, locator_type="xpath") if apply_filter: self.click_element(locator=filter_apply_loc, locator_type="xpath") self.ts.markFinal(apply == checked, "apply is enabled") @allure.step("Chart Digest - filter icon enabled") def verify_filter_icon_enabled(self, enabled, table): filter = self.is_enabled(locator="dashboard-{}-filter-dd".format(table)) self.ts.markFinal(filter == enabled, "filter icon is enabled: {}".format(filter)) @allure.step("Chart Digest - select table tab") def select_tab(self, tab): locator_el = "dashboard-{}-tab".format(tab) self.scroll_to_element(locator=locator_el, locator_type="id") e = self.wait_for_element_clickable(locator=locator_el) self.click_element(element=e) ActionChains(self.driver).move_to_element(to_element=e).click().perform() selected = self.get_attribute_value(locator=locator_el, attribute="data-selected") == "selected" self.ts.markFinal(selected, "tab: {} is selected".format(tab)) @allure.step("Chart Digest - select table section") def select_section_for_table(self, section): e = self.wait_for_element_clickable(locator="dashboard-{}-scope-bar".format(section)) self.click_element(element=e) selected = self.get_attribute_value(locator="dashboard-{}-scope-bar".format(section), attribute="data-selected") == "selected" self.ts.markFinal(selected, "section: {} is selected".format(section)) @allure.step("Chart Digest - verify filtering flow for table") def verify_filtering_flow_for_table(self, table, market_before, market_after, modal=False): no_tracks = self.is_element_displayed(locator="//*[contains(text(), 'No tracks exited')]", locator_type="xpath") if not no_tracks: self.click_filter_icon_table(table=table) self.verify_filter_window_for_table(table=table) self.click_on_page_title(modal=modal) self.verify_filter_window_for_table(open=False, table=table) for t in list(range(0, 4)): self.click_filter_icon_table(table=table) self.verify_filter_window_for_table(table=table) self.click_filter_icon_table(table=table) self.verify_filter_window_for_table(open=False, table=table) self.click_filter_icon_table(table=table) self.filter_check_sony_tracks(apply_filter=False, table=table) self.click_on_page_title(modal=modal) self.verify_filter_window_for_table(open=False, table=table) self.click_filter_icon_table(table=table) self.filter_check_sony_tracks(apply_filter=True, table=table) self.verify_filter_window_for_table(open=False, table=table) top_view_names = self.get_names_from_table(table=table, modal=modal) self.ts.markFinal( all("SONY" in n for n in top_view_names), "sony tracks only in top view table: {}".format(top_view_names), ) self.click_filter_icon_table(table=table) self.filter_check_non_sony_tracks(apply_filter=True, table=table) non_sony_names = self.get_names_from_table(table=table, modal=modal) self.ts.markFinal(all("SONY" not in n for n in non_sony_names), "non sony tracks only in top view table") if modal: self.close_chart_changes_popup() self.trackPage.select_market(market_after) if modal: self.verify_empty_chart_changes() else: names_algeria = self.get_names_from_table(table=table, modal=modal) self.verify_filter_icon_enabled(enabled=False, table=table) self.ts.markFinal(len(names_algeria) == 0, "no track for algeria market") self.trackPage.select_market(market_before) @allure.step("Chart Digest - open chart changes popup") def open_chart_changes_popup(self): self.scroll_to_element(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-title")) displayed = self.is_element_displayed(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) count = 0 if displayed: popup_button = self.get_element(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) count = int(str(self.get_text(element=popup_button)).split("(")[1].replace(")", "")) self.click_element(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) popup = self.is_element_displayed(*self.locator(self.chart_digest_locators, "chart-changes-popup-title")) self.ts.markFinal(popup, "popup is opened") return displayed, count @allure.step("Chart Digest - close chart changes popup") def close_chart_changes_popup(self): self.click_element(*self.locator(self.chart_digest_locators, "chart-changes-popup-close")) @allure.step("Chart Digest - verify empty chart changes displayed") def verify_empty_chart_changes(self, tab=TAB_SPOTIFY): self.scroll_to_element(*self.locator(self.chart_digest_locators, "chart-changes-entries")) self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "chart-changes-entries")) entries = self.get_text(*self.locator(self.chart_digest_locators, "chart-changes-entries")) exits = self.get_text(*self.locator(self.chart_digest_locators, "chart-changes-exits")) if tab == self.TAB_SPOTIFY: t = "Spotify" else: t = "Apple Music" self.ts.markFinal( entries == f"""There were no new entries to the {t} Daily chart today.""", "text is: {}".format(entries), ) self.ts.markFinal( exits == f"""There were no exits from the {t} Daily chart today.""", "text is: {}".format(exits), ) @allure.step("Chart Digest - verify title hover tooltip") def verify_title_hover(self, table, tab): icon = self.is_element_displayed(locator="//*[contains(@class, 'icon-major-moves')]", locator_type="xpath") title = self.get_element(locator="dashboard-{}-title".format(table)) ActionChains(self.driver).move_to_element(to_element=title).perform() tooltip = self.get_text(locator="dashboard-{}-title-tooltip".format(table)) expected_tooltip = "" if table == self.MAJOR_MOVES: if tab == self.TAB_APPLE: expected_tooltip = "Today's major chart movements in the Apple Music Daily chart." else: expected_tooltip = "Today's major chart movements in the Spotify Daily chart." elif table == self.CHART_CHANGES: if tab == self.TAB_SPOTIFY: expected_tooltip = "Today's new entries and exits in the Spotify Daily chart." else: expected_tooltip = "Today's new entries and exits in the Apple Music Daily chart." self.ts.markFinal(tooltip == expected_tooltip, "tooltip is: {}, expected: {}".format(tooltip, expected_tooltip)) self.ts.markFinal(icon, "mm icon is displayed") @allure.step("Chart Digest - get position trends for table") def mm_next_page(self): next_page_locator = "dashboard-major-moves-table-table-pagination-next" time.sleep(1) self.scroll_to_element(next_page_locator, "id") next_page_el = self.get_element(next_page_locator) self.click_element(element=next_page_el) @allure.step("Chart Digest - get position trends for table") def get_position_trends_for_table(self, table, without_blue_dots=True): locator_el = "//*[contains(@id, 'dashboard-{}-table-cell-change-')]" if table in [self.TOP_VIEW, self.BUBBLING_UNDER]: locator_el = "//*[contains(@id, 'dashboard-{}-table-cell-trend-')]" trends_el = self.get_elements(locator=locator_el.format(table), locator_type="xpath") trends = [] if without_blue_dots: for e in trends_el: if str(self.get_text(element=e)) != "": trends.append(int(self.get_text(element=e))) else: for e in trends_el: if str(self.get_text(element=e)) == "": dot_index = trends_el.index(e) + 1 self.verify_trend_blue_dot_present(index=dot_index, table=table) trends.append("blue_dot") else: trends.append(int(self.get_text(element=e))) self.log.info("trends: {}".format(trends)) return trends @allure.step("Chart Digest - get track_position for table") def get_track_position_for_table(self, table): trends_el = self.get_elements(locator="//*[contains(@id, 'dashboard-{}-table-cell-position-')]".format(table), locator_type="xpath") trends = [int(str(self.get_text(element=e)).split(" ")[0]) for e in trends_el] self.log.info("track positions: {}".format(trends)) return trends @allure.step("Chart Digest - get track icons for table") def get_track_icons_for_table(self, table): icons_el = self.get_elements(locator="//*[contains(@id, 'dashboard-{}-table-cell-image-')]".format(table), locator_type="xpath") return icons_el @allure.step("Chart Digest - click on track name in table") def click_on_track_name_in_table(self, table, index=1): selector = f"//*[@id='dashboard-{table}-table-table-cell-name-{index}']/..//*[contains(@href, '/track/')]" title_el = self.wait_for_element_visible(locator=selector, locator_type="xpath") title_cd = self.get_text(element=title_el) self.log.info(f"title cd: {title_cd}") title_el = self.wait_for_element_clickable(locator=selector, locator_type="xpath") self.click_on_element_js(element=title_el) title_tp = self.trackPage.get_track_title() assert_that(title_cd).is_equal_to_ignoring_case(title_tp) @allure.step("Chart Digest - click on artist and verify hover for apple in table") def verify_hover_artist_for_table(self, table, tab, index=1): self.scroll_to_element( locator="//*[@id='dashboard-{}-table-table-cell-name-{}']/div/span/div/div".format(table, index), locator_type="xpath", ) e = self.get_element( locator="//*[@id='dashboard-{}-table-table-cell-name-{}']/div/span/div/div".format(table, index), locator_type="xpath", ) self.click_element(element=e) ActionChains(self.driver).move_to_element(to_element=e).click().perform() tooltip = self.get_text(locator="dashboard-{}-table-table-cell-tooltip-artists".format(table)) if tab == self.TAB_APPLE: tooltip_expected = "Artist and album pages are not available for the track." self.ts.markFinal(tooltip == tooltip_expected, "tooltip is correct for apple tab") @allure.step("Chart Digest - verify Major Moves is empty") def verify_major_moves_empty(self): e = self.is_element_displayed(*self.locator(self.chart_digest_locators, "mm_empty")) self.ts.markFinal(e, "major moves section is empty") @allure.step("Chart Digest - verify Major Moves api and ui") def mm_compare_api_and_ui(self, market, vendor): api_response = self.api_client.get_major_moves_tracks(market=market, vendor=vendor) tracks_number = self.get_mm_total_tracks() total_trends = [] total_positions = [] total_names = [] total_artists = [] number_of_pages = (tracks_number - 1) // 20 for page in range(number_of_pages + 1): trends = self.get_position_trends_for_table(table="{}-table".format(self.MAJOR_MOVES)) for t in trends: total_trends.append(t) positions = self.get_track_position_for_table(table="{}-table".format(self.MAJOR_MOVES)) for p in positions: total_positions.append(p) names_and_artists = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) self.log.info("Names and artists: " + str(names_and_artists)) names = [str(n).split("\n")[0].replace(" ", " ") for n in names_and_artists] for n in names: total_names.append(n) if vendor == self.TAB_APPLE: artists = [str(str(n).split("\n")[1]).strip() for n in names_and_artists] for a in artists: total_artists.append(a) elif vendor == self.TAB_SPOTIFY: artists = [str(str(n).replace("SONY\n", "").split("\n")[1]).strip() for n in names_and_artists] for a in artists: total_artists.append(a) if tracks_number > 20: self.mm_next_page() self.log.info("Total trends: " + str(total_trends)) self.log.info("Total positions: " + str(total_positions)) self.log.info("Total names: " + str(total_names)) self.log.info("Total artists: " + str(total_artists)) trends_api = [abs(api_response["tracks"][t]["trend"]) for t in range(len(api_response["tracks"]))] positions_api = [api_response["tracks"][n]["position"] for n in range(len(api_response["tracks"]))] names_api = [api_response["tracks"][n]["name"].replace(" ", " ") for n in range(len(api_response["tracks"]))] artists_api = [api_response["tracks"][n]["artist"] for n in range(len(api_response["tracks"]))] assert_that(tracks_number).is_equal_to(len(api_response["tracks"])) assert_that(total_trends).is_equal_to(trends_api) assert_that(total_positions).is_equal_to(positions_api) assert_that(total_names).is_equal_to(names_api) assert_that(total_artists).is_equal_to(artists_api) @allure.step("Chart Digest - get Major Moves total track count") def get_mm_total_tracks(self): total_el = self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-total")) total = int(self.get_text(element=total_el)) return total @allure.step("Chart Digest - get Major Moves pagination present") def is_mm_pagination_present(self): caption_el = self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-showing")) caption_text = int(self.get_text(element=caption_el).split(" ")[5]) self.log.info(f"caption text: {caption_text}") return caption_text > 20 @allure.step("Chart Digest - verify Major Moves pagination") def mm_verify_pagination(self): if self.is_mm_pagination_present(): self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-prev")) self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-prev")) self.scroll_to_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-prev")) names_before = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) self.click_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-prev")) names_after = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) caption = self.get_text(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-showing")) total = self.get_mm_total_tracks() self.ts.markFinal(caption == "Showing 1 – 20 of {} results".format(total), "caption is shown: {}".format(caption)) self.ts.markFinal( names_before == names_after, "previous button is not enabled: before: {},\n after: {}".format(names_before, names_after), ) @allure.step("Chart Digest - verify Major Moves hover and pagination") def verify_hover_and_pagination(self): if self.is_mm_pagination_present(): self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) self.scroll_to_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) e = self.get_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) attr_before = e.value_of_css_property("background-color") ActionChains(self.driver).move_to_element(to_element=e).perform() attr_after = e.value_of_css_property("background-color") self.ts.markFinal(attr_after != attr_before, "before: {}, after: {}".format(attr_before, attr_after)) @allure.step("Chart Digest - Major Moves switch page") def mm_switch_page_to(self, page): if self.is_mm_pagination_present(): loc_el = "//*[@id='dashboard-major-moves-table-table-pagination']/..//*[text()='{}']/parent::div".format(page) self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) self.scroll_to_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) e = self.get_element(locator=loc_el, locator_type="xpath") names_before = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) caption_before = self.get_text(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-showing")) self.click_element(element=e) time.sleep(2) caption_after = self.get_text(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-showing")) names_after = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) self.ts.markFinal(20 >= len(names_before) >= len(names_after) > 0, "count of tracks in major moves is 20") track_count1 = caption_after.split(" ")[-4] track_count2 = caption_after.split(" ")[-2] self.log.info(f"caption_before: {caption_before}\ncaption_after: {caption_after}\ntrack_count1: {track_count1}\ntrack_count2: {track_count2}") assert_that(caption_before != caption_after or track_count1 == track_count2).is_true() @allure.step("Chart Digest - Major Moves select last page") def mm_select_last_page(self): if self.is_mm_pagination_present(): self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "mm_pages")) last_page = self.get_elements(*self.locator(self.chart_digest_locators, "mm_pages"))[-1] page_num = self.get_text(element=last_page) self.mm_switch_page_to(page_num) names_before = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) self.click_element(*self.locator(self.chart_digest_locators, "dashboard-major-moves-table-table-pagination-next")) names_after = self.get_names_from_table("{}-table".format(self.MAJOR_MOVES)) self.ts.markFinal( names_before == names_after, "next button is not enabled: before: {},\n after: {}".format(names_before, names_after), ) @allure.step("Chart Digest - Major Moves verify no pagination") def mm_verify_no_pagination(self): pagination = self.get_elements(*self.locator(self.chart_digest_locators, "mm_pages")) self.ts.markFinal(len(pagination) == 0, "pagination is not displayed") @allure.step("Chart Digest - get tracks elements for table") def get_tracks_for_table(self, table): selector = f"//*[contains(@id, 'dashboard-{table}-table-cell-name-')]/..//*[contains(@href, '/track/')]" self.wait_for_element_visible(locator=selector, locator_type="xpath") self.wait_for_element_clickable(locator=selector, locator_type="xpath") elements = self.get_elements(locator=selector, locator_type="xpath") self.log.info(f"Tracks for table: {[self.get_text(element=e) for e in elements]}") return [self.get_text(element=e) for e in elements], elements @allure.step("Chart Digest - get artists elements for table") def get_artists_for_table(self, table): elements = self.get_elements( locator="//*[contains(@id, 'dashboard-{}-table-cell-name-')]/..//*[contains(@href, '/artist/')]".format(table), locator_type="xpath", ) return [str(self.get_text(element=e)).replace(",", "").replace("\\", "") for e in elements], elements @allure.step("Chart Digest - get artists elements for table") def get_artists_for_table_apple(self, table): loc_basic = "//*[contains(@id, 'dashboard-{}-table-cell-name-')]" loc = loc_basic + "/*/*[2]/*/*" self.wait_for_element_visible(locator=loc.format(table), locator_type="xpath") elements = self.get_elements(locator=loc.format(table), locator_type="xpath") texts = [str(self.get_text(element=e)).replace("\\", "") for e in elements] self.log.info("apple artists: {}".format(texts)) return [texts, elements] @allure.step("Chart Digest - get track icons for table") def get_track_images_for_table(self, table): icons_el = self.get_elements(locator="//*[contains(@id, 'dashboard-{}-table-cell-image-')]".format(table), locator_type="xpath") return icons_el @allure.step("Get present tracks names") def get_present_tracks_names(self): elements = self.get_elements(*self.locator(self.chart_digest_locators, "dashboard-all-present-cards-tracks-names")) names = [self.get_text(element=n) for n in elements] self.log.info("Track cards names present:{}".format(names)) return names @allure.step("Navigate to Most Visited first card") def navigate_to_most_visited_first_card(self): elements = self.get_elements(*self.locator(self.chart_digest_locators, "dashboard-all-present-cards-tracks-names")) self.click_element(element=elements[0]) @allure.step("Get expected tracks names") def get_expected_tracks_names(self, track_list): expected_tracks_names_list = [track["name"] for track in list(track_list)] expected_tracks_names_list.reverse() expected_tracks_names_list.remove(expected_tracks_names_list[len(track_list) - 1]) self.log.info("Track cards names expected:{}".format(expected_tracks_names_list)) return expected_tracks_names_list @allure.step("Click on artist name") def click_on_artist_name(self, index): element = self.wait_for_element_clickable(locator="dashboard-most-visited-card-{}-artist-name".format(index)) self.click_element(element=element) @allure.step("CHart Digest - get most visited cards(track, artist, label)") def get_most_visited_cards(self): elements = self.get_elements(*self.locator(self.chart_digest_locators, "most_visited_cards")) text = [self.get_text(element=e) for e in elements] return text @allure.step("Chart Digest - open top charts from table") def open_top_charts_from_table(self, b): self.page_has_loaded() time.sleep(5) self.scroll_to_element(locator="dashboard-{}-btn".format(b), locator_type="id") self.wait_for_element_visible(locator="dashboard-{}-btn".format(b)) self.wait_for_element_clickable(locator="dashboard-{}-btn".format(b)) self.click_element(locator="dashboard-{}-btn".format(b)) self.topChartsPage.top_chart_page_is_opened() @allure.step("CHart Digest - verify sorting for table column") def verify_sorting(self, table, column): if column == "trend": if table == self.MAJOR_MOVES: if column == "trend": column = "change" column_header = "dashboard-{table}-table-table-cell-{column}".format(table=table, column=column) column_values = "//*[contains(@id, 'dashboard-{table}-table-table-cell-{column}-')]/..//span[2]".format(table=table, column=column) else: column_header = "dashboard-{table}-table-cell-{column}".format(table=table, column=column) column_values = "//*[contains(@id, 'dashboard-{table}-table-cell-{column}-')]//../span[2]".format(table=table, column=column) self.scroll_to_element(locator=column_header, locator_type="id") self.click_element(locator=column_header) elements_desc = self.get_elements(locator=column_values, locator_type="xpath") elements_desc = [int(str(self.get_text(element=e)).split(" ")[0]) for e in elements_desc if len(str(self.get_text(element=e))) > 0] self.click_element(locator=column_header) elements_asc = self.get_elements(locator=column_values, locator_type="xpath") elements_asc = [int(str(self.get_text(element=e)).split(" ")[0]) for e in elements_asc if len(str(self.get_text(element=e))) > 0] self.log.info(f"els desc: {elements_desc}\nels asc: {elements_asc}") if 0 in elements_desc: self.ts.markFinal( elements_desc[: elements_desc.index(0)] == sorted(elements_desc[: elements_desc.index(0)], reverse=True), "sorting correct desc: {}".format(elements_desc[: elements_desc.index(0)]), ) self.ts.markFinal( elements_desc[elements_desc.index(0) :] == sorted(elements_desc[elements_desc.index(0) :]), "sorting correct desc p 2: {}".format(elements_desc[: elements_desc.index(0)]), ) if 0 in elements_asc: self.ts.markFinal( elements_asc[: elements_asc.index(0)] == sorted(elements_asc[: elements_asc.index(0)], reverse=True), "sorting correct asc: {}".format(elements_asc[: elements_asc.index(0)]), ) self.ts.markFinal( elements_asc[elements_asc.index(0) :] == sorted(elements_asc[elements_asc.index(0) :]), "sorting correct asc p 2: {}".format(elements_asc[: elements_asc.index(0)]), ) else: self.ts.markFinal(elements_asc == sorted(elements_asc, reverse=True) or elements_asc == natsorted(elements_asc, reverse=True), f"asc sort is correct: {elements_asc}") self.ts.markFinal(elements_desc == sorted(elements_desc, reverse=True) or elements_desc == natsorted(elements_desc, reverse=True), f"desc sort is correct: {elements_desc}") @allure.step("Chart Digest - verify apple artist tooltip") def verify_tooltip_apple_artist(self, table): artists = self.get_artists_for_table_apple(table=table) self.click_element(element=artists[1][0]) ActionChains(self.driver).move_to_element(to_element=artists[1][0]).perform() tooltip = self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "tooltip_artists")) self.ts.markFinal( self.get_text(element=tooltip) == "Artist and album pages are not available for the track.", "tooltip for apple artist is: {}".format(tooltip), ) @allure.step("Chart Digest - get all from table") def get_all_from_table(self, table): tracks = self.get_tracks_for_table(table)[0] artists = self.get_artists_for_table_apple(table)[0] trends = self.get_position_trends_for_table(table) positions = self.get_track_position_for_table(table) images = self.get_track_images_for_table(table) return {"tracks": tracks, "artists": artists, "trends": trends, "positions": positions, "images": images} @allure.step("Chart Digest - verify empty table") def verify_empty_table_top_10_exits(self, tab, table): clock_tooltip = self.get_clock_tooltip_for_table(table) if tab == self.TAB_APPLE: part_1 = """No tracks exited Apple Music's\nTop 10""" text_expected = str(clock_tooltip).replace("Apple Music", part_1) else: part_1 = """No tracks exited Spotify's\nTop 10""" text_expected = str(clock_tooltip).replace("Spotify", part_1) text = self.get_text( locator="//*[contains(@id, 'dashboard-{}')][contains(@id, 'header')]/following-sibling::*/*".format(table), locator_type="xpath", ) self.ts.markFinal(text_expected == text, "empty table text: {}, \nexpected: {}".format(text, text_expected)) @allure.step("Chart Digest - get clock tooltip for table") def get_clock_tooltip_for_table(self, table): clock_element = self.get_element(locator="dashboard-{}-hint-icon".format(table)) ActionChains(self.driver).move_to_element(clock_element).perform() tool = self.get_element(locator="dashboard-{}-hint-icon-tooltip".format(table)) text = self.get_text(element=tool) return text @allure.step("Chart Digest - scroll to section") def scroll_to_section(self, table): self.scroll_to_element(locator="dashboard-{}-title".format(table), locator_type="id") self.page_has_loaded() @allure.step("Chart Digest -verify hover for table header") def verify_hover_for_table_header(self, table): self.scroll_to_section(table) header = self.get_element(locator="dashboard-{}-title".format(table), locator_type="id") ActionChains(self.driver).move_to_element(to_element=header).perform() tool = self.get_text(locator="dashboard-{}-title-tooltip".format(table), locator_type="id") if table == self.BUBBLING_UNDER: self.ts.markFinal(tool == "Tracks that are approaching the top 50.", f"tooltip for table: {table} is: {tool}") @allure.step("Chart Digest -verify chart changes popup elements") def cc_popup_verify_elements(self, count): header = self.is_element_displayed(locator=f"dashboard-{self.CHART_CHANGES}-modal-title") filter = self.is_element_displayed(locator=f"dashboard-{self.CHART_CHANGES}-filter-dd") base_loc = f"//*[contains(@id, 'dashboard-{self.CHART_CHANGES}-modal-item-')]" images = self.get_elements(locator=base_loc + "[contains(@id, 'image')]", locator_type="xpath") names = self.get_elements(locator=base_loc + "[contains(@id, 'name')]", locator_type="xpath") artists = self.get_elements(locator=base_loc + "[contains(@id, 'artist')]", locator_type="xpath") names_clickable = all(n.is_enabled() for n in names) close_icon = self.is_element_displayed(locator=f"dashboard-{self.CHART_CHANGES}-modal-close-icon") self.ts.markFinal(header == filter == names_clickable == close_icon == True, "elements in popup are displayed") self.ts.markFinal(len(images) == len(names) == len(artists) == count, f"images count: {len(images)}") @allure.step("Chart Digest -verify chart changes popup card hover") def cc_popup_verify_card_hover(self): cards = self.get_elements( locator="//*[contains(@id, 'dashboard-chart-changes-modal-item-')][contains(@id, 'image')]/parent::*/parent::*", locator_type="xpath", ) background_before = cards[0].value_of_css_property("background-color") ActionChains(self.driver).move_to_element(to_element=cards[0]).perform() background_after = cards[0].value_of_css_property("background-color") self.ts.markFinal(background_after != background_before, f"background color changed: {background_before}, {background_after}") @allure.step("Chart Digest -verify chart changes popup verify positions") def cc_popup_verify_positions(self, count): elements = self.get_elements( locator=f"//*[contains(@id, 'dashboard-{self.CHART_CHANGES}-modal-item-')][contains(@id, 'position')]", locator_type="xpath", ) positions = [int(str(self.get_text(element=e)).replace("#", "")) for e in elements] entries = positions[: int(count / 2)] exits = positions[int(count / 2) :] self.ts.markFinal(entries == sorted(entries), f"entry positions are sorted: {entries}") self.ts.markFinal(exits == sorted(exits), f"exit positions are sorted: {exits}") @allure.step("Chart Digest -verify chart changes popup height") def cc_popup_verify_height(self): popup = self.get_element(locator="//*[@id='dashboard-chart-changes-modal-title']/parent::*/parent::*/parent::*", locator_type="xpath") min = popup.value_of_css_property("min-height") max = popup.value_of_css_property("max-height") self.ts.markFinal(min == "460px", f"min is: {min}") self.ts.markFinal(max == "640px", f"max is: {max}") @allure.step("Chart Digest -verify chart changes popup click track and verify track page") def cc_popup_click_on_track_and_verify(self): self.wait_for_element_visible( locator=f"//*[contains(@id, 'dashboard-{self.CHART_CHANGES}-modal-item-')][contains(@id, 'name')]", locator_type="xpath", ) names = self.get_elements( locator=f"//*[contains(@id, 'dashboard-{self.CHART_CHANGES}-modal-item-')][contains(@id, 'name')]", locator_type="xpath", ) name = self.get_text(element=names[0]) self.click_element(element=names[0]) title = self.trackPage.get_track_title() self.ts.markFinal(name == title, f"cc name: {name}, tp title: {title}") self.go_back() @allure.step("Chart Changes pop-up - filter tracks by sony or non-sony") def cc_popup_filter_sony_non_sony(self, table, params, cc="popup"): filter_dd = self.wait_for_element_clickable("dashboard-chart-changes-filter-dd") self.click_on_element_js(element=filter_dd) sony_checkbox_locator = "dashboard-chart-changes-filter-dd-checkbox-sony" non_sony_checkbox_locator = "dashboard-chart-changes-filter-dd-checkbox-non_sony" for locator in [sony_checkbox_locator, non_sony_checkbox_locator]: attr_value = self.get_attribute_value(locator, attribute="data-checked") if attr_value == "checked": element = self.get_element(locator=locator) self.click_on_element_js(element=element) for param in params: checkbox = self.get_element(f"dashboard-chart-changes-filter-dd-checkbox-{param}") self.click_on_element_js(element=checkbox) if cc: apply_btn = self.get_element("(//button[contains(@id, 'apply-btn')])[1]", "xpath") else: apply_btn = self.get_element(f"//*[contains(@id, 'dashboard-{table}-title')]/following::button[contains(@id, 'apply-btn')]", "xpath") self.click_on_element_js(element=apply_btn) @allure.step("Chart Changes pop-up - verify no results for both parts") def verify_no_results_both_parts(self): locator = "//span[contains(text(),'No results to show. Try another filter.')]" self.wait_for_element_visible(locator=locator, locator_type="xpath") text = self.get_text(locator=locator, locator_type="xpath") self.ts.markFinal(text == "No results to show. Try another filter.", f"no results text is : {text}") @allure.step("Chart Changes pop-up - verify no results for both parts") def verify_no_results_half_part(self): locator = "//span[contains(text(),'No results to show.')]" self.wait_for_element_visible(locator=locator, locator_type="xpath") text = self.get_text(locator=locator, locator_type="xpath") self.ts.markFinal(text == "No results to show.", f"no results text is : {text}") @allure.step("Chart Digest -verify cc section header and icon") def cc_verify_header_and_icon(self): header = self.is_element_displayed(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-title")) icon = self.is_element_displayed(*self.locator(self.chart_digest_locators, "chart-changes-icon")) self.ts.markFinal(header == icon == True, "heade and icon are displayed for chart changes section") @allure.step("Chart Digest -verify cc section elements") def cc_section_verify_elements(self): entries = self.is_element_displayed(locator="//*[contains(@id, 'entries')][text()='Entries']", locator_type="xpath") exits = self.is_element_displayed(locator="//*[contains(@id, 'exits')][text()='Exits']", locator_type="xpath") base_loc = "//*[contains(@id, 'dashboard-chart-changes-card-')]" images = self.get_elements(locator=base_loc + "[contains(@style, 'image')]", locator_type="xpath") self.wait_for_element_clickable(locator=base_loc + "[contains(@id, 'name')]", locator_type="xpath") names = self.get_elements(locator=base_loc + "[contains(@id, 'name')]", locator_type="xpath") artists = self.get_elements(locator=base_loc + "[contains(@id, 'artist')]", locator_type="xpath") positions = self.get_elements(locator=base_loc + "[contains(@id, 'position')]", locator_type="xpath") positions_int = [int(str(self.get_text(element=p)).replace("#", "")) for p in positions] entry_pos = positions_int[: int(len(positions_int) / 2)] exit_pos = positions_int[int(len(positions_int) / 2) :] names_text = [self.get_text(element=n) for n in names] artists_text = [self.get_text(element=a) for a in artists] self.log.info("UI Artists: " + str(artists_text)) names_clickable = all(n.is_enabled() for n in names) self.ts.markFinal(len(images) == len(names) == len(artists) == len(positions) < 7, f"images count: {len(images)}") self.ts.markFinal(entries == exits == True, "headers are displayed for cc section") self.ts.markFinal(names_clickable, "names in cc section are clickable") self.ts.markFinal(entry_pos == sorted(entry_pos), "entry positions are asc sorted") self.ts.markFinal(exit_pos == sorted(exit_pos), "exit positions are sorted asc") self.log.info("CC section elements: " + str({"names": names_text, "artists": artists_text, "positions": positions_int, "names_el": names})) return {"names": names_text, "artists": artists_text, "positions": positions_int, "names_el": names} @allure.step("Chart Digest -verify cc show all button") def verify_show_all_button(self, count_entries, count_exits): self.page_has_loaded() button = self.get_element(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) count = count_entries + count_exits if count_entries < 4 and count_exits < 4: self.ts.markFinal(not self.is_element_displayed(element=button), "button is not displayed") else: self.scroll_to_element(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) self.wait_for_element_visible(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "dashboard-chart-changes-btn")) self.ts.markFinal( self.get_text(element=button) == f"SHOW ALL ({count})", f"text on button: {self.get_text(element=button)}\n expected: SHOW ALL ({count})", ) @allure.step("Open GTP from dashboard") def open_gtp_from_dashboard(self): self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "gtp-view-button")) self.click_element(*self.locator(self.chart_digest_locators, "gtp-view-button")) @allure.step("Chart Digest - is gtp track present") def get_gtp_tracks_count(self): tracks_present = len(self.api_client.get_gtp_tracks()) return tracks_present @allure.step("Chart Digest - verify GTP banner") def gtp_verify_banner(self): self.page_has_loaded() for e in [ "gtp_spotify_icon", "gtp-card-track-name", "gtp-card-track-artist-name", "gtp-card-streams-value", "gtp-card-streams-title", "gtp-card-hot-hits-title", "gtp-card-chart-position-title", ]: self.wait_for_element_visible(*self.locator(self.chart_digest_locators, e)) gtp_el = self.get_elements(*self.locator(self.chart_digest_locators, e)) self.log.info(f"gtp el: {e}") if e == "gtp_spotify_icon": self.ts.markFinal(len(gtp_el) == 1, f"count of track cards is: {len(gtp_el)}") self.ts.markFinal(self.is_element_displayed(element=gtp_el[0]), f"{e} is displayed on chart digest page") gtp_tracks_count = self.get_gtp_tracks_count() if gtp_tracks_count > 1: gtp_el = self.is_element_displayed(*self.locator(self.chart_digest_locators, "gtp_swipe_controls")) self.ts.markFinal(gtp_el, "gtp_swipe_controls is displayed on chart digest page") pass elif gtp_tracks_count == 1: gtp_el = self.is_element_displayed(*self.locator(self.chart_digest_locators, "gtp_swipe_controls")) self.ts.markFinal(not gtp_el, "gtp_swipe_controls is not displayed on chart digest page") pass else: for e in [ "gtp-card-track-name", "gtp-card-track-artist-name", "gtp-card-hot-hits", "gtp-card-streams-value", ]: gtp_el = self.get_text(*self.locator(self.chart_digest_locators, e)) self.ts.markFinal(gtp_el in ["N/A", "Hot Hits"], f"value for {e} when no tracks in gtp: {gtp_el}") @allure.step("Chart Digest - GTP verify swipe hover") def gtp_swipe_verify_hover(self): gtp_tracks_count = self.get_gtp_tracks_count() if gtp_tracks_count > 1: swipe_el = self.get_element(*self.locator(self.chart_digest_locators, "gtp_swipe_right")) color_before_hover = swipe_el.value_of_css_property("background-color") ActionChains(self.driver).move_to_element(self.get_element(*self.locator(self.chart_digest_locators, "gtp_swipe_right"))).perform() color_after_hover = swipe_el.value_of_css_property("background-color") self.ts.markFinal(color_before_hover != color_after_hover, "Hovering changing color of the swipe button") @allure.step("Chart Digest - GTP get track info") def get_gtp_track_info(self): main_selector = "gtp-card-" track_info = {} track_info_all = [] gtp_tracks_count = self.get_gtp_tracks_count() if gtp_tracks_count == 0: tracks_count = gtp_tracks_count + 1 else: tracks_count = gtp_tracks_count for t in range(tracks_count): for e in self.el_values: self.log.info(f"cd_element: {e}") self.page_has_loaded() time.sleep(2) gtp_el = self.get_elements(*self.locator(self.chart_digest_locators, f"{main_selector}{e}"))[t] gtp_el = self.get_text(element=gtp_el) track_info[e] = gtp_el track_info_all.append(track_info.copy()) self.log.info(f"tracks info gtp on chart digest: {track_info_all}") return track_info_all @allure.step("Chart Digest - GTP swipe left") def gtp_swipe_left(self): gtp_tracks_count = self.get_gtp_tracks_count() if gtp_tracks_count > 1: ActionChains(self.driver).move_to_element(self.get_element(*self.locator(self.chart_digest_locators, "gtp_swipe_left"))).click().perform() @allure.step("Chart Digest - GTP swipe right") def gtp_swipe_right(self): gtp_tracks_count = self.get_gtp_tracks_count() if gtp_tracks_count > 1: ActionChains(self.driver).move_to_element(self.get_element(*self.locator(self.chart_digest_locators, "gtp_swipe_right"))).click().perform() @allure.step("Chart Digest - GTP card - open track") def gtp_card_open_track(self): self.wait_for_element_clickable(*self.locator(self.chart_digest_locators, "gtp_card_track_name")) track_name = self.get_text(*self.locator(self.chart_digest_locators, "gtp_card_track_name")) track_name_link = self.get_element(*self.locator(self.chart_digest_locators, "gtp_card_track_name")) self.click_element(element=track_name_link) track_name_tp = self.trackPage.get_track_title() assert_that(track_name).is_equal_to(track_name_tp) @allure.step("Chart Digest - GTP card - open track") def gtp_card_open_artist(self, index=1): card_artists_locator = "(//*[@id='gtp-card-track-artist-name']//a)[{}]".format(index) self.wait_for_element_clickable(locator=card_artists_locator, locator_type="xpath") artist_name_locator = self.get_element(locator="(//*[@id='gtp-card-track-artist-name']//a)[{}]".format(index), locator_type="xpath") artist_name = str(self.get_text(element=artist_name_locator)).replace(",", "") artist_name_link = self.get_element(locator=card_artists_locator, locator_type="xpath") self.click_element(element=artist_name_link) artist_name_ap = self.artist_page.get_title() assert_that(artist_name).is_equal_to(artist_name_ap) @allure.step("Chart Digest - GTP card - if hot hits empty") def gtp_card_hot_hits_absent(self): is_absent = self.is_element_present(*self.locator(self.chart_digest_locators, "gtp_card_empty_hot_hits")) return is_absent @allure.step("Chart Digest - GTP card - if charts position empty") def gtp_card_charts_position_absent(self): is_absent = self.is_element_present(*self.locator(self.chart_digest_locators, "gtp_card_empty_chart_position")) return is_absent @allure.step("Chart Digest - verify blue dot trend icon present") def verify_trend_blue_dot_present(self, index, table, present=True): trend_dot_sel = f"//*[contains(@id, 'dashboard-{table}-table-cell-trend-{index}')]//../*[contains(@class, 'icon-chart-circle')]" dot = self.is_element_displayed(trend_dot_sel, "xpath") assert_that(dot).is_equal_to(present) @allure.step("Chart Digest - verify trend calculation") def verify_trend_calculation(self, table, vendor, market, token): chart_date_api = self.api_client.get_vendor_api_tracks(vendor=vendor, market=market, token=token)["chart_date"] chart_date = datetime.datetime.strptime(chart_date_api, "%Y-%m-%d").date() previous_chart_date = chart_date - datetime.timedelta(days=1) last_available_chart_info = self.api_client.get_charts_tracks(vendor=vendor, market=market, date=chart_date_api, type="daily") previous_chart_info = self.api_client.get_charts_tracks(vendor=vendor, market=market, date=str(previous_chart_date), type="daily") if table == self.BUBBLING_UNDER: last_available_chart_tracks = last_available_chart_info["tracks"][50:60] elif table == self.TOP_VIEW: last_available_chart_tracks = last_available_chart_info["tracks"][0:10] last_available_trends = [last_available_chart_tracks[t]["trend"] for t in range(len(last_available_chart_tracks)) if abs(last_available_chart_tracks[t]["trend"]) < 1000] last_available_tracks_ids = [last_available_chart_tracks[n]["id"] for n in range(len(last_available_chart_tracks)) if abs(last_available_chart_tracks[n]["trend"]) < 1000] last_available_positions = [last_available_chart_tracks[p]["position"] for p in range(len(last_available_chart_tracks)) if abs(last_available_chart_tracks[p]["trend"]) < 1000] previous_positions = [] for track_id in last_available_tracks_ids: for n in range(len(previous_chart_info["tracks"])): if track_id == previous_chart_info["tracks"][n]["id"]: previous_positions.append(previous_chart_info["tracks"][n]["position"]) calculated_trends = [p2 - p1 for p2, p1 in zip(last_available_positions, previous_positions)] assert_that(last_available_trends).is_equal_to(calculated_trends) calculated_trends_for_ui = [abs(trend) for trend in calculated_trends] ui_trends = self.get_all_from_table(table=table)["trends"] assert_that(calculated_trends_for_ui).is_equal_to(ui_trends) return calculated_trends @allure.step("Chart Digest - Verify trend arrow") def verify_trend_arrow(self, table, index, trend): zero_trend_locator = f"//*[@id='dashboard-{table}-table-cell-trend-{index}']//span[contains(@class, 'icon-arrow-right')]" negative_trend_diag_locator = f"//*[@id='dashboard-{table}-table-cell-trend-{index}']//span[contains(@class, 'icon-arrow-diag-bottom')]" negative_trend_locator = f"//*[@id='dashboard-{table}-table-cell-trend-{index}']//span[contains(@class, 'icon-arrow-down')]" positive_trend_diag_locator = f"//*[@id='dashboard-{table}-table-cell-trend-{index}']//span[contains(@class, 'icon-arrow-diag-top')]" positive_trend_locator = f"//*[@id='dashboard-{table}-table-cell-trend-{index}']//span[contains(@class, 'icon-arrow-up')]" if trend == 0: zero_trend = self.is_element_displayed(locator=zero_trend_locator, locator_type="xpath") assert_that(zero_trend).is_true() elif -4 <= trend < 0: negative_trend_diag = self.is_element_displayed(locator=negative_trend_diag_locator, locator_type="xpath") assert_that(negative_trend_diag).is_true() elif trend < -4: negative_trend = self.is_element_displayed(locator=negative_trend_locator, locator_type="xpath") assert_that(negative_trend).is_true() elif 0 < trend <= 4: positive_trend_diag = self.is_element_displayed(locator=positive_trend_diag_locator, locator_type="xpath") assert_that(positive_trend_diag).is_true() elif 4 < trend <= 1000: positive_trend = self.is_element_displayed(locator=positive_trend_locator, locator_type="xpath") assert_that(positive_trend).is_true() elif 1000 < trend: self.verify_trend_blue_dot_present()