From e69cb173ba63d0e556d4af6cbaf18b11f16af3a9 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 17 Jun 2019 08:11:25 +0200 Subject: Add more e2e tests --- client/e2e/src/po/my-account.ts | 72 ++++++++++++++++ client/e2e/src/po/video-update.po.ts | 20 +++++ client/e2e/src/po/video-watch.po.ts | 43 +++++++++- client/e2e/src/videos.e2e-spec.ts | 159 ++++++++++++++++++++++++++++------- 4 files changed, 264 insertions(+), 30 deletions(-) create mode 100644 client/e2e/src/po/my-account.ts create mode 100644 client/e2e/src/po/video-update.po.ts (limited to 'client/e2e') diff --git a/client/e2e/src/po/my-account.ts b/client/e2e/src/po/my-account.ts new file mode 100644 index 000000000..e49372983 --- /dev/null +++ b/client/e2e/src/po/my-account.ts @@ -0,0 +1,72 @@ +import { by, element } from 'protractor' + +export class MyAccountPage { + + navigateToMyVideos () { + return element(by.css('a[href="/my-account/videos"]')).click() + } + + navigateToMyPlaylists () { + return element(by.css('a[href="/my-account/video-playlists"]')).click() + } + + navigateToMyHistory () { + return element(by.css('a[href="/my-account/history/videos"]')).click() + } + + // My account Videos + + getLastVideoName () { + return this.getAllVideoNameElements().first().getText() + } + + removeLastVideo () { + return this.getLastVideoElement().element(by.css('my-delete-button')).click() + } + + validRemove () { + return element(by.css('.action-button-submit')).click() + } + + countVideos () { + return this.getAllVideoNameElements().count() + } + + // My account playlists + + getLastUpdatedPlaylistName () { + return this.getLastUpdatedPlaylist().element(by.css('.miniature-name')).getText() + } + + getLastUpdatedPlaylistVideosText () { + return this.getLastUpdatedPlaylist().element(by.css('.miniature-playlist-info-overlay')).getText() + } + + clickOnLastUpdatedPlaylist () { + return this.getLastUpdatedPlaylist().element(by.css('.miniature-thumbnail')).click() + } + + countTotalPlaylistElements () { + return element.all(by.css('my-video-playlist-element-miniature')).count() + } + + playPlaylist () { + return element(by.css('.playlist-info .miniature-thumbnail')).click() + } + + // My account Videos + + private getLastVideoElement () { + return element.all(by.css('.video')).first() + } + + private getAllVideoNameElements () { + return element.all(by.css('.video-miniature-name')) + } + + // My account playlists + + private getLastUpdatedPlaylist () { + return element.all(by.css('my-video-playlist-miniature')).first() + } +} diff --git a/client/e2e/src/po/video-update.po.ts b/client/e2e/src/po/video-update.po.ts new file mode 100644 index 000000000..4de3b1b1d --- /dev/null +++ b/client/e2e/src/po/video-update.po.ts @@ -0,0 +1,20 @@ +import { by, element } from 'protractor' + +export class VideoUpdatePage { + + async updateName (videoName: string) { + const nameInput = element(by.css('input#name')) + await nameInput.clear() + await nameInput.sendKeys(videoName) + } + + async validUpdate () { + const submitButton = await this.getSubmitButton() + + return submitButton.click() + } + + private getSubmitButton () { + return element(by.css('.submit-button:not(.disabled) input')) + } +} diff --git a/client/e2e/src/po/video-watch.po.ts b/client/e2e/src/po/video-watch.po.ts index 5f61d5668..9bb0a3919 100644 --- a/client/e2e/src/po/video-watch.po.ts +++ b/client/e2e/src/po/video-watch.po.ts @@ -1,4 +1,4 @@ -import { browser, by, element } from 'protractor' +import { browser, by, element, ElementFinder, ExpectedConditions } from 'protractor' export class VideoWatchPage { async goOnVideosList (isMobileDevice: boolean, isSafari: boolean) { @@ -44,6 +44,10 @@ export class VideoWatchPage { .then(seconds => parseInt(seconds, 10)) } + getVideoName () { + return this.getVideoNameElement().getText() + } + async playAndPauseVideo (isAutoplay: boolean, isMobileDevice: boolean) { if (isAutoplay === false) { const playButton = element(by.css('.vjs-big-play-button')) @@ -101,4 +105,41 @@ export class VideoWatchPage { async goOnP2PMediaLoaderEmbed () { return browser.get('https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50?mode=p2p-media-loader') } + + async clickOnUpdate () { + const dropdown = element(by.css('my-video-actions-dropdown .action-button')) + await dropdown.click() + + const items: ElementFinder[] = await element.all(by.css('my-video-actions-dropdown .dropdown-menu .dropdown-item')) + + for (const item of items) { + const href = await item.getAttribute('href') + + if (href && href.includes('/update/')) { + await item.click() + return + } + } + } + + async clickOnSave () { + return element(by.css('.action-button-save')).click() + } + + async saveToWatchLater () { + return element.all(by.css('my-video-add-to-playlist .playlist')).first().click() + } + + waitUntilVideoName (name: string, maxTime: number) { + const elem = this.getVideoNameElement() + + return browser.wait(ExpectedConditions.textToBePresentInElement(elem, name), maxTime) + } + + private getVideoNameElement () { + // We have 2 video info name block, pick the first that is not empty + return element.all(by.css('.video-bottom .video-info-name')) + .filter(e => e.getText().then(t => !!t)) + .first() + } } diff --git a/client/e2e/src/videos.e2e-spec.ts b/client/e2e/src/videos.e2e-spec.ts index 25521cad9..c19ab3092 100644 --- a/client/e2e/src/videos.e2e-spec.ts +++ b/client/e2e/src/videos.e2e-spec.ts @@ -2,35 +2,56 @@ import { VideoWatchPage } from './po/video-watch.po' import { VideoUploadPage } from './po/video-upload.po' import { LoginPage } from './po/login.po' import { browser } from 'protractor' +import { VideoUpdatePage } from './po/video-update.po' +import { MyAccountPage } from './po/my-account' + +async function skipIfUploadNotSupported () { + if (await isMobileDevice() || await isSafari()) { + console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.') + return true + } + + return false +} + +async function isMobileDevice () { + const caps = await browser.getCapabilities() + return caps.get('realMobile') === 'true' || caps.get('realMobile') === true +} + +async function isSafari () { + const caps = await browser.getCapabilities() + return caps.get('browserName') && caps.get('browserName').toLowerCase() === 'safari' +} describe('Videos workflow', () => { let videoWatchPage: VideoWatchPage - let pageUploadPage: VideoUploadPage + let videoUploadPage: VideoUploadPage + let videoUpdatePage: VideoUpdatePage + let myAccountPage: MyAccountPage let loginPage: LoginPage + const videoName = new Date().getTime() + ' video' - let isMobileDevice = false - let isSafari = false + let videoWatchUrl: string beforeEach(async () => { videoWatchPage = new VideoWatchPage() - pageUploadPage = new VideoUploadPage() + videoUploadPage = new VideoUploadPage() + videoUpdatePage = new VideoUpdatePage() + myAccountPage = new MyAccountPage() loginPage = new LoginPage() - const caps = await browser.getCapabilities() - isMobileDevice = caps.get('realMobile') === 'true' || caps.get('realMobile') === true - isSafari = caps.get('browserName') && caps.get('browserName').toLowerCase() === 'safari' - - if (isMobileDevice) { + if (await isMobileDevice()) { console.log('Mobile device detected.') } - if (isSafari) { + if (await isSafari()) { console.log('Safari detected.') } }) - it('Should log in', () => { - if (isMobileDevice || isSafari) { + it('Should log in', async () => { + if (await isMobileDevice() || await isSafari()) { console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.') return } @@ -39,24 +60,18 @@ describe('Videos workflow', () => { }) it('Should upload a video', async () => { - if (isMobileDevice || isSafari) { - console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.') - return - } + if (await skipIfUploadNotSupported()) return - await pageUploadPage.navigateTo() + await videoUploadPage.navigateTo() - await pageUploadPage.uploadVideo() - return pageUploadPage.validSecondUploadStep(videoName) + await videoUploadPage.uploadVideo() + return videoUploadPage.validSecondUploadStep(videoName) }) it('Should list videos', async () => { - await videoWatchPage.goOnVideosList(isMobileDevice, isSafari) + await videoWatchPage.goOnVideosList(await isMobileDevice(), await isSafari()) - if (isMobileDevice || isSafari) { - console.log('Skipping because we are on a real device or Safari and BrowserStack does not support file upload.') - return - } + if (await skipIfUploadNotSupported()) return const videoNames = videoWatchPage.getVideosListName() expect(videoNames).toContain(videoName) @@ -65,14 +80,16 @@ describe('Videos workflow', () => { it('Should go on video watch page', async () => { let videoNameToExcept = videoName - if (isMobileDevice || isSafari) videoNameToExcept = await videoWatchPage.clickOnFirstVideo() + if (await isMobileDevice() || await isSafari()) videoNameToExcept = await videoWatchPage.clickOnFirstVideo() else await videoWatchPage.clickOnVideo(videoName) - return videoWatchPage.waitWatchVideoName(videoNameToExcept, isMobileDevice, isSafari) + return videoWatchPage.waitWatchVideoName(videoNameToExcept, await isMobileDevice(), await isSafari()) }) it('Should play the video', async () => { - await videoWatchPage.playAndPauseVideo(true, isMobileDevice) + videoWatchUrl = await browser.getCurrentUrl() + + await videoWatchPage.playAndPauseVideo(true, await isMobileDevice()) expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) }) @@ -81,7 +98,7 @@ describe('Videos workflow', () => { await videoWatchPage.goOnAssociatedEmbed() - await videoWatchPage.playAndPauseVideo(false, isMobileDevice) + await videoWatchPage.playAndPauseVideo(false, await isMobileDevice()) expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) await browser.waitForAngularEnabled(true) @@ -92,9 +109,93 @@ describe('Videos workflow', () => { await videoWatchPage.goOnP2PMediaLoaderEmbed() - await videoWatchPage.playAndPauseVideo(false, isMobileDevice) + await videoWatchPage.playAndPauseVideo(false, await isMobileDevice()) expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) await browser.waitForAngularEnabled(true) }) + + it('Should update the video', async () => { + if (await skipIfUploadNotSupported()) return + + await browser.get(videoWatchUrl) + + await videoWatchPage.clickOnUpdate() + + await videoUpdatePage.updateName('my new name') + + await videoUpdatePage.validUpdate() + + const name = await videoWatchPage.getVideoName() + expect(name).toEqual('my new name') + }) + + it('Should add the video in my playlist', async () => { + if (await skipIfUploadNotSupported()) return + + await videoWatchPage.clickOnSave() + await videoWatchPage.saveToWatchLater() + + await videoUploadPage.navigateTo() + + await videoUploadPage.uploadVideo() + await videoUploadPage.validSecondUploadStep('second video') + + await videoWatchPage.clickOnSave() + await videoWatchPage.saveToWatchLater() + }) + + it('Should have the watch later playlist in my account', async () => { + if (await skipIfUploadNotSupported()) return + + await myAccountPage.navigateToMyPlaylists() + + const name = await myAccountPage.getLastUpdatedPlaylistName() + expect(name).toEqual('Watch later') + + const videosNumberText = await myAccountPage.getLastUpdatedPlaylistVideosText() + expect(videosNumberText).toEqual('2 videos') + + await myAccountPage.clickOnLastUpdatedPlaylist() + + const count = await myAccountPage.countTotalPlaylistElements() + expect(count).toEqual(2) + }) + + it('Should watch the playlist', async () => { + if (await skipIfUploadNotSupported()) return + + await myAccountPage.playPlaylist() + + await videoWatchPage.waitUntilVideoName('second video', 20000 * 1000) + }) + + it('Should have the video in my account', async () => { + if (await skipIfUploadNotSupported()) return + + await myAccountPage.navigateToMyVideos() + + const lastVideoName = await myAccountPage.getLastVideoName() + expect(lastVideoName).toEqual('second video') + }) + + it('Should delete the last video', async () => { + if (await skipIfUploadNotSupported()) return + + await myAccountPage.removeLastVideo() + await myAccountPage.validRemove() + + const count = await myAccountPage.countVideos() + expect(count).toEqual(1) + }) + + it('Should delete the first video', async () => { + if (await skipIfUploadNotSupported()) return + + await myAccountPage.removeLastVideo() + await myAccountPage.validRemove() + + const count = await myAccountPage.countVideos() + expect(count).toEqual(0) + }) }) -- cgit v1.2.3