diff --git a/client/e2e/fixtures/video.mp4 b/client/e2e/fixtures/video.mp4 index 35678362b..f9c9e2dd6 100644 Binary files a/client/e2e/fixtures/video.mp4 and b/client/e2e/fixtures/video.mp4 differ diff --git a/client/e2e/protractor.conf.js b/client/e2e/protractor.conf.js index 7b5f8de43..a4fd12473 100644 --- a/client/e2e/protractor.conf.js +++ b/client/e2e/protractor.conf.js @@ -4,7 +4,7 @@ const {SpecReporter} = require('jasmine-spec-reporter') exports.config = { - allScriptsTimeout: 11000, + allScriptsTimeout: 25000, specs: [ './src/**/*.e2e-spec.ts' ], @@ -22,12 +22,6 @@ exports.config = { browserName: 'Chrome', version: '66' }, - { - browserName: 'Chrome', - version: '66', - os: 'android', - - }, { browserName: 'Safari', version: '11.1' @@ -42,16 +36,35 @@ exports.config = { }, { browserName: 'Edge', - version: '17' - } + version: '16' + }, + { + browserName: 'Chrome', + device: 'Google Nexus 6', + realMobile: 'true', + os_version: '5.0' + }, + // { + // browserName: 'Safari', + // device: 'iPhone 6s', + // realMobile: 'true', + // os_version: '9.0' + // }, + // { + // browserName: 'Safari', + // device: 'iPhone SE', + // realMobile: 'true', + // os_version: '11.2' + // } ], maxSessions: 1, - baseUrl: 'http://localhost:4200/', + // BrowserStack compatible ports: https://www.browserstack.com/question/664 + baseUrl: 'http://localhost:3333/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, - defaultTimeoutInterval: 30000, + defaultTimeoutInterval: 45000, print: function () {} }, diff --git a/client/e2e/src/app.e2e-spec.ts b/client/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 5b648207b..000000000 --- a/client/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AppPage } from './po/app.po' - -describe('PeerTube app', () => { - let page: AppPage - - beforeEach(() => { - page = new AppPage() - }) - - it('Should display the app title', () => { - page.navigateTo() - expect(page.getHeaderTitle()).toEqual('PeerTube') - }) -}) diff --git a/client/e2e/src/po/app.po.ts b/client/e2e/src/po/app.po.ts deleted file mode 100644 index e3e293d7b..000000000 --- a/client/e2e/src/po/app.po.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { browser, by, element } from 'protractor' - -export class AppPage { - navigateTo () { - browser.waitForAngularEnabled(false) - return browser.get('/') - } - - getHeaderTitle () { - return element(by.css('.instance-name')).getText() - } -} diff --git a/client/e2e/src/po/login.po.ts b/client/e2e/src/po/login.po.ts index 5a36fd611..40f958d2b 100644 --- a/client/e2e/src/po/login.po.ts +++ b/client/e2e/src/po/login.po.ts @@ -4,8 +4,10 @@ export class LoginPage { async loginAsRootUser () { await browser.get('/login') - await element(by.css('input#username')).sendKeys('root') - await element(by.css('input#password')).sendKeys('test1') + element(by.css('input#username')).sendKeys('root') + element(by.css('input#password')).sendKeys('test1') + + await browser.sleep(1000) await element(by.css('form input[type=submit]')).click() diff --git a/client/e2e/src/po/video-upload.po.ts b/client/e2e/src/po/video-upload.po.ts index 741914d2d..1ac696107 100644 --- a/client/e2e/src/po/video-upload.po.ts +++ b/client/e2e/src/po/video-upload.po.ts @@ -1,6 +1,6 @@ -import { browser, element, by } from 'protractor' -import { join } from 'path' +import { browser, by, element } from 'protractor' import { FileDetector } from 'selenium-webdriver/remote' +import { join } from 'path' export class VideoUploadPage { navigateTo () { diff --git a/client/e2e/src/po/video-watch.po.ts b/client/e2e/src/po/video-watch.po.ts index b5df1cbc5..0f37e3e33 100644 --- a/client/e2e/src/po/video-watch.po.ts +++ b/client/e2e/src/po/video-watch.po.ts @@ -1,15 +1,24 @@ import { by, element, browser } from 'protractor' export class VideoWatchPage { - async goOnRecentlyAdded () { - const url = '/videos/recently-added' + async goOnVideosList (isIphoneDevice: boolean) { + let url: string + + if (isIphoneDevice === true) { + // Local testing is buggy :/ + url = 'https://peertube2.cpy.re/videos/local' + } else { + url = '/videos/recently-added' + } await browser.get(url) return browser.wait(browser.ExpectedConditions.elementToBeClickable(element(this.getFirstVideoListSelector()))) } getVideosListName () { - return element.all(this.getFirstVideoListSelector()).getText() + return element.all(this.getFirstVideoListSelector()) + .getText() + .then((texts: any) => texts.map(t => t.trim())) } waitWatchVideoName (videoName: string) { @@ -24,7 +33,19 @@ export class VideoWatchPage { .then(seconds => parseInt(seconds, 10)) } - async pauseVideo (pauseAfterMs: number) { + async pauseVideo (pauseAfterMs: number, isMobileDevice: boolean, isIphoneDevice: boolean) { + if (isMobileDevice === true) { + if (isIphoneDevice === false) { + const playButton = element(by.css('.vjs-big-play-button')) + await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton)) + await playButton.click() + } else { + const playButton = element(by.css('video')) + await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton)) + await playButton.click() + } + } + await browser.wait(browser.ExpectedConditions.invisibilityOf(element(by.css('.vjs-loading-spinner')))) const el = element(by.css('div.video-js')) @@ -32,15 +53,30 @@ export class VideoWatchPage { await browser.sleep(pauseAfterMs) - return el.click() + if (isIphoneDevice === true) { + // document.webkitCancelFullScreen() + } else { + return el.click() + } } async clickOnVideo (videoName: string) { const video = element(by.css('.videos .video-miniature .video-thumbnail[title="' + videoName + '"]')) + await browser.wait(browser.ExpectedConditions.elementToBeClickable(video)) + await video.click() + + await browser.wait(browser.ExpectedConditions.urlContains('/watch/')) + } + + async clickOnFirstVideo () { + const video = element(by.css('.videos .video-miniature:first-child .video-miniature-name')) + await browser.wait(browser.ExpectedConditions.elementToBeClickable(video)) + const textToReturn = video.getText() await video.click() await browser.wait(browser.ExpectedConditions.urlContains('/watch/')) + return textToReturn } private getFirstVideoListSelector () { diff --git a/client/e2e/src/videos.e2e-spec.ts b/client/e2e/src/videos.e2e-spec.ts index 82cea72b1..c21bc163e 100644 --- a/client/e2e/src/videos.e2e-spec.ts +++ b/client/e2e/src/videos.e2e-spec.ts @@ -8,18 +8,36 @@ describe('Videos workflow', () => { let pageUploadPage: VideoUploadPage let loginPage: LoginPage const videoName = new Date().getTime() + ' video' + let isMobileDevice = false + let isIphoneDevice = false + + beforeEach(async () => { + browser.waitForAngularEnabled(false) - beforeEach(() => { videoWatchPage = new VideoWatchPage() pageUploadPage = new VideoUploadPage() loginPage = new LoginPage() + + const caps = await browser.getCapabilities() + isMobileDevice = caps.get('realMobile') === 'true' || caps.get('realMobile') === true + isIphoneDevice = caps.get('device') === 'iphone' }) it('Should log in', () => { + if (isMobileDevice) { + console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') + return + } + return loginPage.loginAsRootUser() }) it('Should upload a video', async () => { + if (isMobileDevice) { + console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') + return + } + pageUploadPage.navigateTo() await pageUploadPage.uploadVideo() @@ -27,20 +45,30 @@ describe('Videos workflow', () => { }) it('Should list the video', async () => { - await videoWatchPage.goOnRecentlyAdded() + await videoWatchPage.goOnVideosList(isIphoneDevice) + + if (isMobileDevice) { + console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') + return + } const videoNames = videoWatchPage.getVideosListName() expect(videoNames).toContain(videoName) }) it('Should go on video watch page', async () => { - await videoWatchPage.clickOnVideo(videoName) + let videoNameToExcept = videoName - return videoWatchPage.waitWatchVideoName(videoName) + if (isMobileDevice && isIphoneDevice) videoNameToExcept = 'PeerTube_Mobile.v.1' + + if (isMobileDevice && isIphoneDevice === false) videoNameToExcept = await videoWatchPage.clickOnFirstVideo() + else await videoWatchPage.clickOnVideo(videoName) + + return videoWatchPage.waitWatchVideoName(videoNameToExcept) }) it('Should play the video', async () => { - await videoWatchPage.pauseVideo(2500) + await videoWatchPage.pauseVideo(7000, isMobileDevice, isIphoneDevice) expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) }) }) diff --git a/scripts/e2e.sh b/scripts/e2e.sh index bdd051486..17c8f68ef 100755 --- a/scripts/e2e.sh +++ b/scripts/e2e.sh @@ -10,6 +10,6 @@ npm run clean:server:test ) concurrently -k -s first \ - "cd client && npm run ng -- e2e" \ + "cd client && npm run ng -- e2e --port 3333" \ "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' npm start" diff --git a/server/tests/api/fixtures/video_too_long.webm b/server/tests/api/fixtures/video_too_long.webm deleted file mode 100644 index 8286f74b0..000000000 Binary files a/server/tests/api/fixtures/video_too_long.webm and /dev/null differ