From 61a7e802af5d39074f7a2c7a79bd6ca5742c4b70 Mon Sep 17 00:00:00 2001 From: Kasim Necdet Percinel Date: Mon, 18 Nov 2024 10:34:19 -0500 Subject: [PATCH] Youtube shared videos playwright tests (#646) * news and announcement test * fix comment * fix no youtube video message also for observation date videos * utility function to generate random int * page object for youtube drawer * implement test for the youtube drawer scenarios * some useful renaming * fix typescript style * code style fixes * fix typo bug --- index.php | 3 +- resources/js/UI/UserVideoGallery.js | 23 +- tests/desktop/normal/youtube/youtube.spec.ts | 396 +++++++++++++++++++ tests/page_objects/helioviewer.ts | 11 + tests/page_objects/youtube_drawer.ts | 169 ++++++++ tests/utils/utils.ts | 14 + 6 files changed, 610 insertions(+), 6 deletions(-) create mode 100644 tests/desktop/normal/youtube/youtube.spec.ts create mode 100644 tests/page_objects/youtube_drawer.ts create mode 100644 tests/utils/utils.ts diff --git a/index.php b/index.php index eda1df90f..eadb5975d 100644 --- a/index.php +++ b/index.php @@ -722,7 +722,7 @@ function attr($attr, $file) { - + @@ -741,6 +741,7 @@ function attr($attr, $file) { + diff --git a/resources/js/UI/UserVideoGallery.js b/resources/js/UI/UserVideoGallery.js index f2f8bf6c2..affb7ccb9 100644 --- a/resources/js/UI/UserVideoGallery.js +++ b/resources/js/UI/UserVideoGallery.js @@ -20,7 +20,8 @@ var UserVideoGallery = Class.extend( init : function (url) { this._container = $("#user-video-gallery-main"); this._containerCurrent = $("#user-video-gallery-main-current"); - this._noSharedMoviesFound = $("#user-video-gallery-current .js-no-movies"); + this._noSharedMoviesFound = $("#user-video-gallery .js-no-movies"); + this._noSharedMoviesFoundForObservationDate = $("#user-video-gallery-current .js-no-movies"); this._loader = $("#user-video-gallery-spinner"); this._loaderCurrent = $("#user-video-gallery-spinner-current"); @@ -262,9 +263,15 @@ var UserVideoGallery = Class.extend( count++; }); - if($('.user-video-thumbnail-container-recent').length == 0){ + if($('.user-video-thumbnail-container-current').length == 0){ + this._noSharedMoviesFoundForObservationDate.show(); + } else { + this._noSharedMoviesFoundForObservationDate.hide(); + } + + if($('.user-video-thumbnail-container-recent').length == 0){ this._noSharedMoviesFound.show(); - } else { + } else { this._noSharedMoviesFound.hide(); } @@ -370,14 +377,20 @@ var UserVideoGallery = Class.extend( } if($('.user-video-thumbnail-container-current').length == 0){ - this._noSharedMoviesFound.show(); + this._noSharedMoviesFoundForObservationDate.show(); } else { - this._noSharedMoviesFound.hide(); + this._noSharedMoviesFoundForObservationDate.hide(); if(count == this._numVideosCurrent){ this._containerCurrent.append('SHOW MORE'); } } + if($('.user-video-thumbnail-container-recent').length == 0){ + this._noSharedMoviesFound.show(); + } else { + this._noSharedMoviesFound.hide(); + } + $('#user-video-gallery-main-current > div').off(); $('#user-video-gallery-main-current > div').hover(function(){ var id = $(this).data('id'); diff --git a/tests/desktop/normal/youtube/youtube.spec.ts b/tests/desktop/normal/youtube/youtube.spec.ts new file mode 100644 index 000000000..8d14a6c31 --- /dev/null +++ b/tests/desktop/normal/youtube/youtube.spec.ts @@ -0,0 +1,396 @@ +import { test, expect } from "@playwright/test"; +import { Helioviewer } from "../../../page_objects/helioviewer"; +import { getRandomInt } from "../../../utils/utils"; + +/** + * Test Steps for checking recently shared videos are rendered correctly + * 1 ) Mock some data for recently shared youtube videos: + * 2 ) Open youtube drawer + * 3 ) Assert all videos mocked before are visible in viewport with correct links and titles + */ +test("Recently shared youtube videos should be rendered correctly with correct link and title", async ({ + page +}, info) => { + let hv = new Helioviewer(page, info); + + const mockedMovies = []; + const mockedMoviesData = []; + const moviesLength = getRandomInt(1, 40); + + // Prepare some mock data for the recently shared youtube videos + for (let i = 0; i < moviesLength; i++) { + const hoursAgo = getRandomInt(1, 100); + + const id = Math.random().toString(36).substring(2, 7); // Generate random id + const startDate = new Date(Date.now() - hoursAgo * 3600000).toISOString(); // n hours ago for startdate + const publishedDate = startDate; // same as startdate + const endDate = new Date().toISOString(); // now + + mockedMovies.push({ + id: id, + url: `http://foo.com/watch?v=${id}`, + thumbnails: { + icon: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + small: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + medium: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + large: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + full: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png" + }, + published: publishedDate, + title: `AIA 131 (${startDate} - ${endDate} UTC)`, + description: `This movie was mocked by playwright tests`, + keywords: "SDO,AIA,131,1", + imageScale: "0.915297", + dataSourceString: `[SDO,AIA,131,1,86,0,60,1,2024-01-10T18:46:22.000Z]`, + eventSourceString: "", + movieLength: (Math.random() * 10).toFixed(5), + width: "1552", + height: "760", + startDate: startDate, + endDate: endDate + }); + + // Remember what we have mocked so we can assert them later + mockedMoviesData.push({ + id: id, + hoursAgo: hoursAgo + }); + } + + // 0. Mock API requests + await page.route("*/**/?action=getUserVideos*", async (route) => { + await route.fulfill({ json: mockedMovies }); + }); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. CLICK YOUTUBE BUTTON TO SHOW YOUTUBE VIDOS + await hv.toggleYoutubeVideosDrawer(); + await hv.WaitForLoadingComplete(); + + // Assert youtube drawer is open and correct number of videos visible in drawer + await hv.youtubeDrawer.assertDrawerOpen(); + await hv.youtubeDrawer.assertYoutubeSharedVideoCount(mockedMoviesData.length); + + // Assert all mocked videos are visibile with correct links and title + for (const mov of mockedMoviesData) { + let title = `${mov.hoursAgo} hours ago`; + let daysAgo = Math.floor(mov.hoursAgo / 24); + + if (mov.hoursAgo >= 24) { + title = `${daysAgo} day ago`; + } + + if (mov.hoursAgo >= 48) { + title = `${daysAgo} days ago`; + } + + await hv.youtubeDrawer.assertYoutubeSharedVideoVisibleWithTitle(mov.id, title); + await hv.youtubeDrawer.assertYoutubeSharedVideoGoesToLink(mov.id, `http://foo.com/watch?v=${mov.id}`); + } +}); + +/** + * Test Steps for checking visibility of a friendly message when there is no recently shared videos. + * 1 ) Mock empty data response for recently shared youtube videos: + * 2 ) Open youtube drawer + * 3 ) Assert all no videos should be visible + * 4 ) Assert the visibility of friendly no video message + */ +test("If there is no youtube movies then there should be a friendly message", async ({ page }, info) => { + let hv = new Helioviewer(page, info); + + // 0. Mock API requests for no videos + await page.route("*/**/?action=getUserVideos*", async (route) => { + await route.fulfill({ json: [] }); + }); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. CLICK NEWS BUTTON TO SHOW YOUTUBE VIDOS + await hv.toggleYoutubeVideosDrawer(); + await hv.WaitForLoadingComplete(); + + // 3) Assert no videos in the drawer + await hv.youtubeDrawer.assertYoutubeSharedVideoCount(0); + + // 4) Assert no video message is visible + await hv.youtubeDrawer.assertNoYoutubeSharedVideoMessage(); +}); + +/** + * Test Steps for checking observation date shared videos are rendered correctly + * 1 ) Mock some data for observation date shared youtube videos: + * 2 ) Open youtube drawer + * 3 ) Toggle visibility for observation date shared videos accordion inside drawer + * 4 ) Assert all videos mocked before are visible in viewport with correct links and titles + */ +test("Youtube movies around observation date should be rendered correctly", async ({ page }, info) => { + let hv = new Helioviewer(page, info); + + const mockedMovies = []; + const mockedMoviesData = []; + const moviesLength = getRandomInt(1, 40); + + // Prepare some mock data for the recently shared youtube videos + for (let i = 0; i < moviesLength; i++) { + const hoursAgo = getRandomInt(1, 100); + + const id = Math.random().toString(36).substring(2, 7); // Generate random id + const startDate = new Date(Date.now() - hoursAgo * 3600000).toISOString(); // n hours ago + const publishedDate = startDate; // n hours ago + const endDate = new Date().toISOString(); // now + + mockedMovies.push({ + id: id, + url: `http://anotherfoo.com/watch?v=${id}`, + thumbnails: { + icon: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + small: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + medium: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + large: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + full: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png" + }, + published: publishedDate, + title: `AIA 131 (${startDate} - ${endDate} UTC)`, + description: `This movie was mocked by playwright tests`, + keywords: "SDO,AIA,131,1", + imageScale: "0.915297", + dataSourceString: `[SDO,AIA,131,1,86,0,60,1,2024-01-10T18:46:22.000Z]`, + eventSourceString: "", + movieLength: (Math.random() * 10).toFixed(5), + width: "1552", + height: "760", + startDate: startDate, + endDate: endDate, + roi: { + top: Math.floor(Math.random() * (600 - 300 + 1)) + 300, // Random between 300 and 600 + left: Math.floor(Math.random() * (-700 - -1000 + 1)) + -1000, // Random between -1000 and -700 + bottom: Math.floor(Math.random() * (1400 - 1100 + 1)) + 1100, // Random between 1100 and 1400 + right: Math.floor(Math.random() * (700 - 500 + 1)) + 500, // Random between 500 and 700 + imageScale: parseFloat((Math.random() * (1.5 - 1.0) + 1.0).toFixed(5)), // Random between 1.0 and 1.5 + width: Math.floor(Math.random() * (1600 - 1400 + 1)) + 1400, // Random between 1400 and 1600 + height: Math.floor(Math.random() * (750 - 650 + 1)) + 650 // Random between 650 and 750 + } + }); + + // Remember what we have mocked so we can assert them later + mockedMoviesData.push({ + id: id, + startDate: startDate, + endDate: endDate + }); + } + + // 0. Mock API requests + await page.route("*/**/?action=getObservationDateVideos*", async (route) => { + await route.fulfill({ json: mockedMovies }); + }); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. CLICK YOUTUBE BUTTON TO SHOW YOUTUBE VIDOS + await hv.toggleYoutubeVideosDrawer(); + + // 3 TOGGLE VISIBILITY FOR OBSERVATION DATE SHARED VIDEOS ACCORDION INSIDE DRAWER + await hv.youtubeDrawer.toggleObservationDateYoutubeSharedAccordion(); + await hv.WaitForLoadingComplete(); + + // Assert correct number of videos visible in drawer + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoCount(mockedMoviesData.length); + + // Assert all mocked videos are visibile with correct links and title + for (const mov of mockedMoviesData) { + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoVisibleWithTitle( + mov.id, + `AIA 131 (${mov.startDate} ${mov.endDate} UTC)` + ); + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoGoesToLink( + mov.id, + `http://anotherfoo.com/watch?v=${mov.id}` + ); + } +}); + +/** + * Test Steps for checking visibility of a friendly message when there is no observation date youtube shared videos. + * 1 ) Mock empty data response for observation date shared youtube videos: + * 2 ) Open youtube drawer + * 3 ) Toggle visibility for observation date shared videos accordion inside drawer + * 4 ) Assert all no videos should be visible + * 5 ) Assert the visibility of friendly no video message + */ +test("If there is no youtube movies around observation date then there should be a friendly message", async ({ + page +}, info) => { + let hv = new Helioviewer(page, info); + + // 0. Mock API requests + await page.route("*/**/?action=getObservationDateVideos*", async (route) => { + await route.fulfill({ json: [] }); + }); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. CLICK NEWS BUTTON TO SHOW YOUTUBE VIDEOS + await hv.toggleYoutubeVideosDrawer(); + + // 3. Toggle visibility for observation date shared videos accordion inside drawer + await hv.youtubeDrawer.toggleObservationDateYoutubeSharedAccordion(); + // 4. Assert all no videos should be visible + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoCount(0); + + // 5. Assert the visibility of friendly no video message + await hv.youtubeDrawer.assertNoObservationDateYoutubeSharedVideoMessage(); +}); + +/** + * Test Steps for checking observation date shared video location markers visibility can be controlled from ui checkbox + * 1 ) Mock some data for observation date shared youtube videos: + * 2 ) Open youtube drawer + * 3 ) Toggle visibility for observation date shared videos accordion inside drawer + * 4 ) Check checkbox for showing location markers for videos + * 5 ) Assert all markers are visible for the mocked videos + * 4 ) Uncheck checkbox for showing location markers for videos + * 5 ) Assert no markers are visible for the mocked videos + */ +test("Youtube movies around observation date should show markers if the 'show in viewport' checkbox is checked", async ({ + page +}, info) => { + let hv = new Helioviewer(page, info); + + const mockedMovies = []; + const mockedMoviesData = []; + const moviesLength = getRandomInt(1, 40); + + // Mock some data for shared videos + for (let i = 0; i < moviesLength; i++) { + const hoursAgo = getRandomInt(1, 100); + + const id = Math.random().toString(36).substring(2, 7); // Generate random id + const startDate = new Date(Date.now() - hoursAgo * 3600000).toISOString(); // n hours ago + const publishedDate = startDate; // n hours ago + const endDate = new Date().toISOString(); // now + + mockedMovies.push({ + id: id, + url: `http://anotherfoo.com/watch?v=${id}`, + thumbnails: { + icon: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + small: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + medium: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + large: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png", + full: "https://helioviewer.org/resources/images/viewyoutube_icon_transp.png" + }, + published: publishedDate, + title: `AIA ${id} (${startDate} - ${endDate} UTC)`, + description: `This movie was mocked by playwright tests`, + keywords: "SDO,AIA,131,1", + imageScale: "0.915297", + dataSourceString: `[SDO,AIA,131,1,86,0,60,1,2024-01-10T18:46:22.000Z]`, + eventSourceString: "", + movieLength: (Math.random() * 10).toFixed(5), + width: "1552", + height: "760", + startDate: startDate, + endDate: endDate, + roi: { + top: Math.floor(Math.random() * (600 - 300 + 1)) + 300, // Random between 300 and 600 + left: Math.floor(Math.random() * (-700 - -1000 + 1)) + -1000, // Random between -1000 and -700 + bottom: Math.floor(Math.random() * (1400 - 1100 + 1)) + 1100, // Random between 1100 and 1400 + right: Math.floor(Math.random() * (700 - 500 + 1)) + 500, // Random between 500 and 700 + imageScale: parseFloat((Math.random() * (1.5 - 1.0) + 1.0).toFixed(5)), // Random between 1.0 and 1.5 + width: Math.floor(Math.random() * (1600 - 1400 + 1)) + 1400, // Random between 1400 and 1600 + height: Math.floor(Math.random() * (750 - 650 + 1)) + 650 // Random between 650 and 750 + } + }); + + mockedMoviesData.push({ + id: id, + startDate: startDate, + endDate: endDate + }); + } + + await page.route("*/**/?action=getObservationDateVideos*", async (route) => { + await route.fulfill({ json: mockedMovies }); + }); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. CLICK YOUTUBE BUTTON TO SHOW YOUTUBE VIDOS + await hv.toggleYoutubeVideosDrawer(); + await hv.WaitForLoadingComplete(); + + // 3 TOGGLE VISIBILITY FOR OBSERVATION DATE SHARED VIDEOS ACCORDION INSIDE DRAWER + await hv.youtubeDrawer.toggleObservationDateYoutubeSharedAccordion(); + await hv.WaitForLoadingComplete(); + + // 4 Check checkbox for showing location markers for videos + await hv.youtubeDrawer.showSunLocationMarkersForForObservationDateVideos(); + + // 5 Assert all markers are visible for the mocked videos + for (const mov of mockedMoviesData) { + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoMarkersVisibleWithTitle(`AIA ${mov.id}`); + } + + // 6 Check checkbox again for hiding location markers for videos + await hv.youtubeDrawer.hideSunLocationMarkersForForObservationDateVideos(); + + // 7 Assert all markers are NOT visible for the mocked videos + for (const mov of mockedMoviesData) { + await hv.youtubeDrawer.assertObservationDateYoutubeSharedVideoMarkersNotVisibleWithTitle(`AIA ${mov.id}`); + } +}); + +/** + * Test Steps for checking observation date shared videos are updated when the observation date changes + * 1) Load hv + * 2) Open youtube drawer + * 3) Toggle visibility for observation date shared videos accordion inside drawer + * 4) Set observation date to one week back of current datetime + * 5) Expect a request to be made to fetch new videos for observation date + */ +test("Youtube observation date videos should be updated with the observation date change ", async ({ page }, info) => { + let hv = new Helioviewer(page, info); + + // 1. LOAD HV + await hv.Load(); + await hv.CloseAllNotifications(); + + // 2. Open Sidebar to control date + await hv.OpenImageLayerDrawer(); + + // 3. Open youtube drawer + await hv.toggleYoutubeVideosDrawer(); + await hv.WaitForLoadingComplete(); + + // 4. Open observation date videos accordion + await hv.youtubeDrawer.toggleObservationDateYoutubeSharedAccordion(); + + // Calculate observation date to one week before the current date + const initialDate = await hv.GetLoadedDate(); + const oneWeekOfSeconds = 604800; + const oneWeekBeforeDate = new Date(initialDate.getTime() - oneWeekOfSeconds * 1000); + const oneWeekBeforeDateURLEncoded = encodeURIComponent(oneWeekBeforeDate.toISOString().slice(0, 19)); + + // 5. Expect a request to be made to fetch new youtube videos around new observation date + const fetchNewObservationDateYoutubeRequestPromise = page.waitForRequest( + new RegExp(`\\?action=getObservationDateVideos\\&date=${oneWeekBeforeDateURLEncoded}`) + ); + + // 6. Set the observation date one week back , + await hv.JumpBackwardsDateWithSelection(oneWeekOfSeconds); // Go one week backwards + + await fetchNewObservationDateYoutubeRequestPromise; +}); diff --git a/tests/page_objects/helioviewer.ts b/tests/page_objects/helioviewer.ts index 7d7eb7bee..f26d886c3 100644 --- a/tests/page_objects/helioviewer.ts +++ b/tests/page_objects/helioviewer.ts @@ -9,6 +9,7 @@ import { Movie } from "./movie"; import { URLShare } from "./urlshare"; import { EventTree } from "./event_tree"; import { VSODrawer } from "./vso_drawer"; +import { YoutubeDrawer } from "./youtube_drawer"; import { ScaleIndicator } from "./scale_indicator"; import * as fs from "fs"; import { DesktopInterface } from "./helioviewer_interface"; @@ -32,6 +33,7 @@ class Helioviewer implements DesktopInterface { urlshare: URLShare; vso_drawer: VSODrawer; scale_indicator: ScaleIndicator; + youtubeDrawer: YoutubeDrawer; constructor(page: Page, info: TestInfo | null = null) { this.page = page; @@ -42,6 +44,7 @@ class Helioviewer implements DesktopInterface { this.vso_drawer = new VSODrawer(this.page); this.scale_indicator = new ScaleIndicator(this.page); this.sidebar = this.page.locator("#hv-drawer-left"); + this.youtubeDrawer = new YoutubeDrawer(this.page); } /** @@ -509,6 +512,14 @@ class Helioviewer implements DesktopInterface { async toggleNewsAndAnnouncements(): Promise { await this.page.locator("#news-button").click(); } + + /** + * Click youtube button in top controls to see the shared youtube videos + * @returns {Promise} + */ + async toggleYoutubeVideosDrawer(): Promise { + await this.page.locator("#youtube-button").click(); + } } export { Helioviewer }; diff --git a/tests/page_objects/youtube_drawer.ts b/tests/page_objects/youtube_drawer.ts new file mode 100644 index 000000000..3455bd634 --- /dev/null +++ b/tests/page_objects/youtube_drawer.ts @@ -0,0 +1,169 @@ +import { Page, Locator, expect } from "@playwright/test"; + +/** + * Interface for interacting with elements related to youtube shared videos drawer drawer + */ +class YoutubeDrawer { + /** Playwright page instance */ + private page: Page; + private drawer: Locator; + private accordionYoutube: Locator; + private accordionObservationDate: Locator; + + constructor(page: Page) { + this.page = page; + this.drawer = this.page.locator("#hv-drawer-youtube"); + this.accordionYoutube = this.drawer.locator("#accordion-youtube"); + this.accordionObservationDate = this.drawer.locator("#accordion-youtube-current"); + } + + /** + * Assert drawer is open + * @returns {Promise} + */ + async assertDrawerOpen(): Promise { + await expect(this.drawer).toBeVisible(); + } + + /** + * Assert drawer is closed + * @returns {Promise} + */ + async assertDrawerClose(): Promise { + await expect(this.drawer).not.toBeVisible(); + } + + /** + * Assert video count of youtube shared videos + * @param {number} count expected video number + * @returns {Promise} + */ + async assertYoutubeSharedVideoCount(count: number): Promise { + await expect(this.accordionYoutube.locator("img").locator("visible=true")).toHaveCount(count); + } + + /** + * Assert video count of observation date youtube shared videos + * @param {number} count expected video number + * @returns {Promise} + */ + async assertObservationDateYoutubeSharedVideoCount(count: number): Promise { + await expect(this.accordionObservationDate.locator("img").locator("visible=true")).toHaveCount(count); + } + + /** + * Assert visibility of video and its title for shared youtube videos + * @param {string} id of video + * @param {string} title for the video + * @returns {Promise} + */ + async assertYoutubeSharedVideoVisibleWithTitle(id: string, title: string): Promise { + await expect(this.accordionYoutube.locator(`#youtube-movie-current-${id}`)).toBeVisible(); + await expect(this.accordionYoutube.locator(`#youtube-movie-current-${id}`).locator("xpath=..")).toHaveText(title); + } + + /** + * Assert visibility of video and its title for observation date shared youtube videos + * @param {string} id of video + * @param {string} title for the video + * @returns {Promise} + */ + async assertObservationDateYoutubeSharedVideoVisibleWithTitle(id: string, title: string): Promise { + await expect(this.accordionObservationDate.locator(`#youtube-movie-current-${id}`)).toBeVisible(); + await expect(this.accordionObservationDate.locator(`#youtube-movie-current-${id}`).locator("xpath=..")).toHaveText( + title + ); + } + + /** + * Assert the video link for given shared youtube video + * @param {string} id of video + * @param {string} link for the video + * @returns {Promise} + */ + async assertYoutubeSharedVideoGoesToLink(id: string, link: string): Promise { + await expect(this.accordionYoutube.locator(`#youtube-movie-current-${id}`)).toBeVisible(); + await expect(this.accordionYoutube.locator(`#youtube-movie-current-${id}`)).toHaveAttribute("href", link); + } + + /** + * Assert the video link for given shared observation date youtube video + * @param {string} id of video + * @param {string} link for the video + * @returns {Promise} + */ + async assertObservationDateYoutubeSharedVideoGoesToLink(id: string, link: string): Promise { + await expect(this.accordionObservationDate.locator(`#youtube-movie-current-${id}`)).toBeVisible(); + await expect(this.accordionObservationDate.locator(`#youtube-movie-current-${id}`)).toHaveAttribute("href", link); + } + + /** + * Assert visibility of helpful message when there is no youtube shared video + * @returns {Promise} + */ + async assertNoYoutubeSharedVideoMessage(): Promise { + await expect(this.accordionYoutube.locator("#user-video-gallery")).toHaveText("No shared movies found."); + } + + /** + * Assert visibility of helpful message when there is no observation date youtube shared video + * @returns {Promise} + */ + async assertNoObservationDateYoutubeSharedVideoMessage(): Promise { + await expect(this.accordionObservationDate.locator("#user-video-gallery-current")).toContainText( + "No movies found around the observation date." + ); + } + + /** + * Toggle visibility of youtube shared videos accordion inside the youtube drawer + * @returns {Promise} + */ + async toggleYoutubeSharedAccordion(): Promise { + await this.accordionYoutube.locator(".header").click(); + } + + /** + * Toggle visibility of youtube observation date shared videos accordion inside the youtube drawer + * @returns {Promise} + */ + async toggleObservationDateYoutubeSharedAccordion(): Promise { + await this.accordionObservationDate.locator(".header").click(); + } + + /** + * Enable visibility of video markers indicating locations of the recorded video + * @returns {Promise} + */ + async showSunLocationMarkersForForObservationDateVideos(): Promise { + await this.accordionObservationDate.locator("#movies-show-in-viewport").check(); + } + + /** + * Disable visibility of video markers indicating locations of the recorded video + * @returns {Promise} + */ + async hideSunLocationMarkersForForObservationDateVideos(): Promise { + await this.accordionObservationDate.locator("#movies-show-in-viewport").uncheck(); + } + + /** + * Assert visibility for observation date youtube video markers are visible + * @param {string} markerTitle of the marker + * @returns {Promise} + */ + async assertObservationDateYoutubeSharedVideoMarkersVisibleWithTitle(markerTitle: string): Promise { + await expect(this.page.getByRole("link", { name: markerTitle })).toBeVisible(); + } + + /** + * Assert no-visibility for observation date youtube video markers are visible + * @param {string} markerTitle of the marker + * @returns {Promise} + */ + async assertObservationDateYoutubeSharedVideoMarkersNotVisibleWithTitle(markerTitle: string): Promise { + await expect(this.page.getByRole("link", { name: markerTitle })).not.toBeVisible(); + } +} + +export { YoutubeDrawer }; diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts new file mode 100644 index 000000000..09abdf20b --- /dev/null +++ b/tests/utils/utils.ts @@ -0,0 +1,14 @@ +/** + * Generates a random integer within a specified range (inclusive). + * + * @param {number} min - The minimum integer value that can be returned. + * @param {number} max - The maximum integer value that can be returned. + * @returns {number} A random integer between the specified min and max values, inclusive. + */ +function getRandomInt(min: number, max: number): number { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +export { getRandomInt };