import json from datetime import datetime from allure import step from assertpy import assert_that from playwright.sync_api import Page from src.pages.common_page import CommonPage from src.ui_elements.base_ui_element import BaseUIElement from src.locators.discovery_results_locators import DiscoveryResultsLocators from src.helpers import api_helper class DiscoveryResultsPage(CommonPage): def __init__(self, page: Page): super().__init__(page) self.page = page self.url = '/discovery/result' self.api_saved_discoveries = f"**{api_helper.api_saved_discoveries}" self.title_discovery_results = BaseUIElement(self.page, DiscoveryResultsLocators.TITLE_DISCOVERY_RESULTS, 'Discovery Results page title') self.bn_edit_discovery = BaseUIElement(self.page, DiscoveryResultsLocators.BN_EDIT_DISCOVERY, 'Edit Discovery button') self.bn_save_discovery = BaseUIElement(self.page, DiscoveryResultsLocators.BN_SAVE_DISCOVERY, 'Save Discovery button') self.bn_save_discovery_entity = BaseUIElement(self.page, DiscoveryResultsLocators.BN_SAVE_DISCOVERY_ENTITY, 'Save Discovery Entity button') self.placeholder_discovery_name = BaseUIElement(self.page, DiscoveryResultsLocators.PLACEHOLDER_DISCOVERY_NAME, 'Discovery Name placeholder') self.bn_see_discovery_summary = BaseUIElement(self.page, DiscoveryResultsLocators.BN_SEE_DISCOVERY_SUMMARY, 'See Discovery Summary button') self.bn_hide_discovery_summary = BaseUIElement(self.page, DiscoveryResultsLocators.BN_HIDE_DISCOVERY_SUMMARY, 'Hide Discovery Summary button') self.discovery_summary = BaseUIElement(self.page, DiscoveryResultsLocators.DISCOVERY_SUMMARY_PANEL, 'Discovery Summary panel') self.discovery_summary_item = BaseUIElement(self.page, DiscoveryResultsLocators.DISCOVERY_SUMMARY_ITEM, 'Discovery Summary item') self.discovery_summary_filter_item = BaseUIElement(self.page, DiscoveryResultsLocators.DISCOVERY_SUMMARY_FILTER_ITEM, 'Discovery Summary filter item') self.bn_next_page = BaseUIElement(self.page, DiscoveryResultsLocators.BN_NEXT_PAGE, 'Next Page button') self.bn_return_to_saved_discoveries = BaseUIElement( self.page, DiscoveryResultsLocators.BN_RETURN_TO_SAVED_DISCOVERIES, 'Return To Saved Discoveries button') self.card_item = self.page.locator(DiscoveryResultsLocators.ARTIST_ITEM) self.card_image = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_IMG, 'Artist Card - Image') self.card_green_mark = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_IMG_GREEN_MARK, 'Artist Card - Green mark on Image') self.card_name = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_NAME, 'Artist Card - Name') self.card_chart_title = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_CHART_TITLE, 'Artist Card - Chart Title') self.card_chart = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_CHART, 'Artist Card - Chart') self.card_chart_error = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_NO_CHART, 'Artist Card - No Chart Error') self.card_kpi_item = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_KPI_ITEM, 'Artist KPI item') self.card_dsp = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_DSP, 'Artist Card - DSP button') self.card_menu = BaseUIElement(self.page, DiscoveryResultsLocators.ARTIST_MENU, 'Artist Card - Menu') @step("Discovery Results page is loaded") def is_page_loaded(self): self.title_discovery_results.exists() @step("Count cards on the page") def cards_count(self): return self.card_item.count() def page_cards_id_list(self): card_ids = list() print("Count artists on the page: {}".format(self.cards_count())) for i in range(self.cards_count()): card_ids.append(self.card_item.nth(i).get_attribute("data-entity-id")) return card_ids @staticmethod def response_artist_id_list(response): response_json = response.value.json() response_ids = list() for i in range(len(response_json)): response_ids.append(response_json[i]['id']) return response_ids @step("Compare artist IDs from response and on the page") def compare_cards_lists_for_page_vs_response(self, discovery_response): response_ids = self.response_artist_id_list(discovery_response) page_ids = self.page_cards_id_list() print('Artist IDs in response \n{}'.format(response_ids)) print('Artist IDs on the page \n{}'.format(page_ids)) assert_that(response_ids).is_equal_to(page_ids) @step("Sorting rules check") # https://data-analytics.atlassian.net/wiki/spaces/DNA/pages/2419327058/Sorting+Rules def verify_sorting(self, discovery_response, dsp, sorting_parameter): current_top = None response = discovery_response.value.json() for entity in response: print("Verify entity id: {}".format(entity['id'])) print("DSP data: {}".format(entity[dsp])) delta = entity[dsp][sorting_parameter]['period_28_days_data']['change'] chart_data = entity[dsp]['chart_data'] last = chart_data[-1] if len(chart_data) > 7: last_7 = chart_data[-8] else: last_7 = chart_data[0] if 'release_date' in entity and entity['release_date'] is not None: release_date = datetime.strptime(entity['release_date'], '%Y-%m-%d').date() day_diff = (datetime.today().date() - release_date).days print(f"{datetime.today().date()} - {release_date} => {day_diff}") if day_diff <= 7: last_7 = 0 print("{} - {} ?= {}".format(last, last_7, delta)) assert_that(delta).is_equal_to(last - last_7) if current_top is not None: print("Previous {}: {}".format(sorting_parameter, current_top)) print("Current {}: {}".format(sorting_parameter, delta)) assert_that(current_top >= delta).is_true() current_top = delta @step("Verify sorting rules for Artist") def verify_artist_sorting_rules(self, discovery_response, dsp): sorting_by = {'tiktok': 'followers', 'spotify': 'listeners', 'youtube': 'subscribers', 'soundcloud': 'followers'} self.verify_sorting(discovery_response, dsp, sorting_by[dsp]) @step("Verify sorting rules for Track") def verify_track_sorting_rules(self, discovery_response, dsp): sorting_by = {'tiktok': 'views', 'spotify': 'streams', 'youtube': 'views', 'soundcloud': 'plays'} self.verify_sorting(discovery_response, dsp, sorting_by[dsp]) @step("Verify data on artist card for DSP - {dsp}") def verify_artist_card(self, dsp, discovery_response): self.is_page_loaded() response = discovery_response.value.json() for i in range(len(response)): artist_id = response[i]['id'] print("Verify user id: {} from response index = {}".format(artist_id, i)) # Check active DSP dsp_ui = "sndcld" if dsp == 'soundcloud' else dsp self.card_dsp.get_by(artist_id, dsp_ui).is_active() # Check card image source img_url = self.card_image.get_by(artist_id).get_attribute("src") assert_that(img_url).contains('image') assert_that(img_url == response[i]['artwork_url'] or img_url == response[i]['artwork_url_alt']).is_true() # Check name name = self.card_name.get_by(artist_id).get_text() assert_that(name).is_equal_to(response[i]['name']) # Check chart presence and title try: self.card_chart.get_by(artist_id).exists() chart_title = self.card_chart_title.get_by(artist_id).get_text() assert_that(chart_title.split('/')[0]).is_equal_to(response[i][dsp]['chart_type'].capitalize()) except AssertionError: print('Not enough historical data to build a sparkline.') self.card_chart_error.get_by(artist_id).exists() # Check KPI items kpis = {'tiktok': ['Followers', 'Likes', 'Creations'], 'youtube': ['Subscribers', 'Views', 'Videos'], 'spotify': ['Followers', 'Listeners', 'Popularity'], 'soundcloud': ['Followers', 'Likes', 'Plays']} print('Data from payload:') print(response[i][dsp][kpis[dsp][0].lower()]) print(response[i][dsp][kpis[dsp][1].lower()]) # due to renamed TikTok Videos->Creations resp_in_kpi_2 = 'Videos' if kpis[dsp][2] == 'Creations' else kpis[dsp][2] print(response[i][dsp][resp_in_kpi_2.lower()]) # Check that card's KPI contains digit or =N/A. 1st element is taken to check artist_kpi_1 = self.card_kpi_item.get_by(artist_id, 1, kpis[dsp][0]).get_text() artist_kpi_2 = self.card_kpi_item.get_by(artist_id, 2, kpis[dsp][1]).get_text() artist_kpi_3 = self.card_kpi_item.get_by(artist_id, 3, kpis[dsp][2]).get_text() assert_that(artist_kpi_1[0].isdigit() or artist_kpi_1 == 'N/A').is_true() assert_that(artist_kpi_1[0].isdigit() or artist_kpi_2 == 'N/A').is_true() assert_that(artist_kpi_1[0].isdigit() or artist_kpi_3 == 'N/A').is_true() @step("Verify data on track card for DSP - {dsp}") def verify_track_card(self, dsp, discovery_response): self.is_page_loaded() response = discovery_response.value.json() for i in range(len(response)): track_id = response[i]['id'] print("Verify user id: {} from response index = {}".format(track_id, i)) # Check active DSP dsp_ui = "sndcld" if dsp == 'soundcloud' else dsp self.card_dsp.get_by(track_id, dsp_ui).is_active() # Check card image source img_url = self.card_image.get_by(track_id).get_attribute("src") assert_that(img_url).contains('image') assert_that(img_url == response[i]['artwork_url'] or img_url == response[i]['artwork_url_alt']).is_true() # Check name name = self.card_name.get_by(track_id).get_text() assert_that(name).is_equal_to(response[i]['name']) # Check chart presence and title try: self.card_chart.get_by(track_id).exists() chart_title = self.card_chart_title.get_by(track_id).get_text() if chart_title == 'Artist Listeners/Mth': assert_that(response[i][dsp]['chart_type']).is_equal_to("monthly_listeners") elif chart_title == 'Artist Followers': assert_that(response[i][dsp]['chart_type']).is_equal_to("followers") else: assert_that(chart_title.split('/')[0]).is_equal_to(response[i][dsp]['chart_type'].capitalize()) except AssertionError: print('No Chart Error') self.card_chart_error.get_by(track_id).exists() # Check KPI items kpis = {'tiktok': ['Comments', 'Views', 'Likes'], 'youtube': ['Comments', 'Views', 'Likes'], 'spotify': ['Playlists', 'Streams', 'Popularity'], 'soundcloud': ['Followers', 'Likes', 'Plays']} print('Data from payload:') print(response[i][dsp][kpis[dsp][0].lower()]) print(response[i][dsp][kpis[dsp][1].lower()]) print(response[i][dsp][kpis[dsp][2].lower()]) # Check that card's KPI contains digit or = N/A. 1st element is taken to check track_kpi_1 = self.card_kpi_item.get_by(track_id, 1, kpis[dsp][0]).get_text() track_kpi_2 = self.card_kpi_item.get_by(track_id, 2, kpis[dsp][1]).get_text() track_kpi_3 = self.card_kpi_item.get_by(track_id, 3, kpis[dsp][2]).get_text() assert_that(track_kpi_1[0].isdigit() or track_kpi_1 == 'N/A').is_true() assert_that(track_kpi_2[0].isdigit() or track_kpi_2 == 'N/A').is_true() assert_that(track_kpi_3[0].isdigit() or track_kpi_3 == 'N/A').is_true() @step("Verify activated DSP on cards is {activated_dsp}") def verify_card_activated_dsp(self, activated_dsp): self.is_page_loaded() for artist_id in self.page_cards_id_list(): self.card_dsp.get_by(artist_id, activated_dsp).is_active() @step("Verify running saved discovery name") def saved_discovery_name_exists(self, search_type): with open(f'src/data/{search_type}_discovery.json') as json_file: discovery_json = json.load(json_file) discovery_name = discovery_json['name'] self.label_by_text.get_by(discovery_name).exists() @step("Check green mark is present for artist/track card id = {card_id}") def verify_green_mark_for_card(self, card_id): self.card_green_mark.get_by(card_id).exists()