from time import sleep from appium.webdriver.common.appiumby import AppiumBy as By from helpers.platform.ios.locators import ( ios_other_by_name, ios_static_text_by_name) from page_objects.base_screen import BaseScreen class ArtistScreen(BaseScreen): artist_header = 'participantHeader' cover_art = 'coverArt' flag = '' favorite_btn = '' share_btn = 'shareButton' share_header_text = 'headerText' share_link_btn = 'shareLink' share_as_image_btn = 'shareSnapshot' share_close_btn = 'closeButton' spotify_monthly = 'spotifyMonthlyListenersOpacity' spotify = 'SPOTIFY' youtube = 'YOUTUBE' instagram = 'INSTAGRAM' facebook = 'FACEBOOK' deezer = 'DEEZER' # twitter = 'TWITTER' # soundcloud = 'SOUNDCLOUD' manage_linked_accounts_btn = ( ios_other_by_name('MANAGE LINKED ACCOUNTS', index=1)) social_media_title = ios_static_text_by_name('SOCIAL FOLLOWERS') fan_conversion_ratio_btn = 'spotifyFanConversionPercentageOpacity' fan_conversion_title = \ ('**/XCUIElementTypeStaticText[`name == "headerText" and ' 'label == "Fan Conversion Ratio"`]') fan_conversion_content = \ ('Followers divided by monthly listeners. ' 'Not all followers are listeners, but this ratio shows how ' 'effectively the artist is capturing the audience - those who listen ' 'to the music.') fan_conversion_heatmap_meter = 'heatmapMeter' fan_conversion_close_btn = 'closeButton' manage_linked_accounts_title = ( ios_static_text_by_name('MANAGE LINKED ACCOUNTS')) manage_linked_accounts_close_btn = 'closeButton' top_song = ('**/XCUIElementTypeOther[`name BEGINSWITH "topTracksItem" ' 'and accessible == true`]') top_songs_sort_btn = 'sortToggle' song_tile = ios_other_by_name('songTile') see_all_btn = ios_other_by_name('showAllButton', index=1) filters_btn = 'filterToggle' filter_reset_btn = 'resetButton' filters_country = ios_other_by_name('COUNTRY', index=2) filters_country_option = ios_other_by_name('countryRow') filters_apply_btn = 'applyButton' filters_close_btn = 'closeButton' def assert_all_sections(self, artist): self.assert_header(artist) self.assert_summary() self.assert_social_metrics() def assert_header(self, artist): header_id = f'{self.artist_header}-{artist}' self.assert_element(By.ID, header_id, 40) def assert_artist_header_elements_present(self, artist): self.waiter(10, By.ACCESSIBILITY_ID, self.cover_art) def tap_share_button(self): self.click_with_retry(10, By.ACCESSIBILITY_ID, self.share_btn) def assert_share_screen_options_displayed(self): self.waiter(10, By.ACCESSIBILITY_ID, self.share_header_text) self.waiter(3, By.ACCESSIBILITY_ID, self.share_link_btn) # self.waiter(3, By.ACCESSIBILITY_ID, self.share_as_image_btn) self.click_with_retry(3, By.ACCESSIBILITY_ID, self.share_close_btn) def assert_summary(self): self.assert_element(By.ID, self.spotify_monthly, 10) def go_to_section(self, context, section_name): self.scroll_and_assert(By.ACCESSIBILITY_ID, section_name, 5) def assert_social_metrics(self): socials = [self.youtube, self.spotify, self.instagram, self.facebook, self.deezer] for bar_chart in socials: self.scroll_and_assert(By.ID, bar_chart, small_scroll=True, max_scrolls=20) def open_social_followers_from_artist_screen(self): social_followers = ios_other_by_name('SPOTIFY') self.click_with_retry(10, By.IOS_CLASS_CHAIN, social_followers) def assert_social_followers_page_displayed(self): self.waiter(10, By.IOS_CLASS_CHAIN, self.social_media_title) def assert_expected_metrics(self): metrics = [ "FOLLOWERS", "MONTHLY LISTENERS" ] for metric in metrics: metric_loc = ios_static_text_by_name(metric) self.waiter(10, By.IOS_CLASS_CHAIN, metric_loc) self.waiter(5, By.ACCESSIBILITY_ID, self.fan_conversion_ratio_btn) def assert_graph_displayed_for_each_connected_social_network(self): platforms = [ "Spotify Followers", "Instagram Followers", "YouTube Subscribers", # TODO: Temporarily disabled Facebook Fans # "Facebook Fans", # TODO(GO-40355): Temporarily disabled due to ] issue # Re-enable once the issue is resolved # "TikTok Followers", "Deezer Fans" ] for platform in platforms: title_loc = \ f'name == "platform" AND label == "{platform}"' chart_loc = (f'//XCUIElementTypeStaticText[@label="{platform}"]/' f'ancestor::XCUIElementTypeOther[2]//' f'XCUIElementTypeOther[@name="chartContainer"]') self.scroll_and_assert(By.IOS_PREDICATE, title_loc, small_scroll=True, max_scrolls=10) self.scroll_and_assert(By.XPATH, chart_loc, small_scroll=True, max_scrolls=10) def tap_fan_conversion_metric(self): self.scroll_and_assert(By.ACCESSIBILITY_ID, self.fan_conversion_ratio_btn, 10, 'up') self.click_with_retry(3, By.ACCESSIBILITY_ID, self.fan_conversion_ratio_btn) def assert_fan_conversion_ratio_displayed(self): self.waiter(10, By.IOS_CLASS_CHAIN, self.fan_conversion_title) self.waiter(3, By.ACCESSIBILITY_ID, self.fan_conversion_content) self.waiter(3, By.ACCESSIBILITY_ID, self.fan_conversion_heatmap_meter) self.click_with_retry(3, By.ACCESSIBILITY_ID, self.fan_conversion_close_btn) def assert_manage_linked_accounts_visible(self): self.scroll_and_assert(By.IOS_CLASS_CHAIN, self.manage_linked_accounts_btn, max_scrolls=10, small_scroll=True) # Scroll back up slightly to correct overscroll on small-screen devices self.scroll_page(direction='up', small_scroll=True) def tap_manage_linked_accounts_button(self): self.scroll_and_assert(By.IOS_CLASS_CHAIN, self.manage_linked_accounts_btn, small_scroll=True) self.click_with_retry(10, By.IOS_CLASS_CHAIN, self.manage_linked_accounts_btn) def assert_manage_linked_accounts_page_displayed(self): self.waiter(10, By.IOS_CLASS_CHAIN, self.manage_linked_accounts_title) def assert_listed_social_platforms(self, expected_platforms): for platform in expected_platforms: self.waiter(10, By.ACCESSIBILITY_ID, platform.upper()) self.click_with_retry(10, By.ACCESSIBILITY_ID, self.manage_linked_accounts_close_btn) def assert_see_all_button_visible(self): self.scroll_and_assert(By.IOS_CLASS_CHAIN, self.see_all_btn, small_scroll=True, max_scrolls=10) def assert_number_of_displayed_songs(self, number): top_songs = self.waiter(10, By.IOS_CLASS_CHAIN, self.top_song, multiple=True) assert len(top_songs) == int(number) def assert_number_of_displayed_songs_exceed(self, number, timeout=10, poll_interval=1): self.waiter(10, By.ACCESSIBILITY_ID, self.filters_btn) elapsed = 0 while elapsed < timeout: top_songs = self.waiter(5, By.IOS_CLASS_CHAIN, self.top_song, multiple=True) if len(top_songs) > int(number): return sleep(poll_interval) elapsed += poll_interval raise AssertionError( f"Expected more than {number} top songs, but got {len(top_songs)}") def assert_songs_are_sorted_by(self, filter_option): current_filter_option_loc = \ (f'**/XCUIElementTypeOther[`name == "sortToggle" ' f'and label == "{filter_option}"`]') self.waiter(20, By.IOS_CLASS_CHAIN, current_filter_option_loc) def tap_song_number(self, context, song_number): top_songs = self.waiter(10, By.IOS_CLASS_CHAIN, self.top_song, multiple=True) top_songs[song_number].click() def tap_on_bottom_part_of_playlist_card(self, context, card_number): song_tiles = self.waiter( 10, By.IOS_CLASS_CHAIN, self.song_tile, multiple=True) song_tiles[card_number].click() def change_top_songs_sorting_to(self, sorting_option): title = ('**/XCUIElementTypeStaticText[`name == "headerText" ' 'and label == "Sort By"`]') sorting_option_loc = \ f'name == "sortingOption" AND label == "{sorting_option}"' self.click_with_retry(10, By.ACCESSIBILITY_ID, self.top_songs_sort_btn) self.waiter(10, By.IOS_CLASS_CHAIN, title) self.click_with_retry(5, By.IOS_PREDICATE, sorting_option_loc) def tap_see_all_songs_button(self): self.click_with_retry(10, By.IOS_CLASS_CHAIN, self.see_all_btn) def tap_filter_icon(self): self.click_with_retry(10, By.ACCESSIBILITY_ID, self.filters_btn) def select_country_filter(self): self.click_with_retry(10, By.IOS_CLASS_CHAIN, self.filters_country) def assert_country_list_with_global_selected_by_default(self): countries = self.waiter(10, By.IOS_CLASS_CHAIN, self.filters_country_option, multiple=True) assert len(countries) > 10 def select_countries_from_market_selector(self, countries): for country in countries: country_loc = f'name == "countryRow" AND label == "{country}"' self.click_with_retry(10, By.IOS_PREDICATE, country_loc) self.click_with_retry(10, By.ACCESSIBILITY_ID, self.filters_apply_btn) def assert_country_filter_summary(self, countries): summary_loc = \ ios_other_by_name(f'COUNTRY {countries}', index=2) self.waiter(10, By.IOS_CLASS_CHAIN, summary_loc) def assert_country_filter_summary_is_empty(self, excluded_countries): sleep(3) summary_loc = \ ios_other_by_name(f'COUNTRY {excluded_countries}', index=2) self.wait_for_element_invisibility(By.IOS_CLASS_CHAIN, summary_loc, 5) def reset_filter(self): self.click_with_retry(10, By.ACCESSIBILITY_ID, self.filter_reset_btn) def close_filter_window(self): self.click_with_retry(10, By.ACCESSIBILITY_ID, self.filters_close_btn)