Make it works with new autoplay policy
authorChocobozzz <me@florianbigard.com>
Tue, 22 May 2018 14:02:29 +0000 (16:02 +0200)
committerChocobozzz <me@florianbigard.com>
Tue, 22 May 2018 14:02:29 +0000 (16:02 +0200)
client/e2e/protractor.conf.js
client/e2e/src/po/video-upload.po.ts
client/e2e/src/po/video-watch.po.ts
client/e2e/src/videos.e2e-spec.ts
client/src/assets/player/peertube-player.ts
client/src/assets/player/peertube-videojs-plugin.ts
client/src/assets/player/utils.ts
client/src/standalone/videos/embed.ts
package.json
scripts/e2e.sh

index a4fd124739b4415899e0a39234d74ba369831a48..5dcd7728427af0240645e9157020a9329f3356aa 100644 (file)
@@ -5,16 +5,14 @@ const {SpecReporter} = require('jasmine-spec-reporter')
 
 exports.config = {
   allScriptsTimeout: 25000,
-  specs: [
-    './src/**/*.e2e-spec.ts'
-  ],
+  specs: ['./src/**/*.e2e-spec.ts'],
 
   seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub',
   commonCapabilities: {
     'browserstack.user': process.env.BROWSERSTACK_USER,
     'browserstack.key': process.env.BROWSERSTACK_KEY,
     'browserstack.local': true,
-    'project': 'PeerTube'
+    projec: 'PeerTube'
   },
 
   multiCapabilities: [
@@ -24,7 +22,8 @@ exports.config = {
     },
     {
       browserName: 'Safari',
-      version: '11.1'
+      version: '11.1',
+      resolution: '1920x1080'
     },
     {
       browserName: 'Firefox',
@@ -44,35 +43,29 @@ exports.config = {
       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'
-    // }
+    {
+      browserName: 'Safari',
+      device: 'iPhone SE',
+      realMobile: 'true',
+      os_version: '11.2'
+    }
   ],
 
-  maxSessions: 1,
+  // maxSessions: 1,
   // BrowserStack compatible ports: https://www.browserstack.com/question/664
   baseUrl: 'http://localhost:3333/',
   framework: 'jasmine',
   jasmineNodeOpts: {
     showColors: true,
     defaultTimeoutInterval: 45000,
-    print: function () {}
+    print: function() {}
   },
 
-  onPrepare () {
+  onPrepare() {
     require('ts-node').register({
       project: require('path').join(__dirname, './tsconfig.e2e.json')
     })
-    jasmine.getEnv().addReporter(new SpecReporter({spec: {displayStacktrace: true}}))
+    jasmine.getEnv().addReporter(new SpecReporter({   spec:  {  displayStacktrace: true    }  }))
   }
 }
 
index 1ac69610766a755b7f6b4d69f7aa8db79c3d7428..1978707e3a5cb55f79ecb8048f25d87811cc362b 100644 (file)
@@ -3,16 +3,26 @@ import { FileDetector } from 'selenium-webdriver/remote'
 import { join } from 'path'
 
 export class VideoUploadPage {
-  navigateTo () {
-    return browser.get('/videos/upload')
+  async navigateTo () {
+    await element(by.css('.header .upload-button')).click()
+
+    return browser.wait(browser.ExpectedConditions.visibilityOf(element(by.css('.upload-video-container'))))
   }
 
   async uploadVideo () {
     browser.setFileDetector(new FileDetector())
 
     const fileToUpload = join(__dirname, '../../fixtures/video.mp4')
+    const fileInputSelector = '.upload-video-container input[type=file]'
+    const parentFileInput = '.upload-video .button-file'
+
+    // Avoid sending keys on non visible element
+    await browser.executeScript(`document.querySelector('${fileInputSelector}').style.opacity = 1`)
+    // await browser.executeScript(`document.querySelector('${fileInputSelector}').style.opacity = 1`)
+    await browser.executeScript(`document.querySelector('${parentFileInput}').style.overflow = 'initial'`)
 
-    await element(by.css('.upload-video-container input[type=file]')).sendKeys(fileToUpload)
+    const elem = element(by.css(fileInputSelector))
+    await elem.sendKeys(fileToUpload)
 
     // Wait for the upload to finish
     await browser.wait(browser.ExpectedConditions.elementToBeClickable(this.getSecondStepSubmitButton()))
index 0f37e3e33bb528a2dee6a1c8199edaf11a2ca391..19d02ff51b422f16f7331e2bf41f85d46b88e402 100644 (file)
@@ -1,7 +1,7 @@
 import { by, element, browser } from 'protractor'
 
 export class VideoWatchPage {
-  async goOnVideosList (isIphoneDevice: boolean) {
+  async goOnVideosList (isIphoneDevice: boolean, isSafari: boolean) {
     let url: string
 
     if (isIphoneDevice === true) {
@@ -12,11 +12,16 @@ export class VideoWatchPage {
     }
 
     await browser.get(url)
-    return browser.wait(browser.ExpectedConditions.elementToBeClickable(element(this.getFirstVideoListSelector())))
+
+    // Waiting the following element does not work on Safari...
+    if (isSafari === true) return browser.sleep(3000)
+
+    const elem = element.all(by.css('.videos .video-miniature .video-miniature-name')).first()
+    return browser.wait(browser.ExpectedConditions.visibilityOf(elem))
   }
 
   getVideosListName () {
-    return element.all(this.getFirstVideoListSelector())
+    return element.all(by.css('.videos .video-miniature .video-miniature-name'))
                   .getText()
                   .then((texts: any) => texts.map(t => t.trim()))
   }
@@ -33,19 +38,19 @@ export class VideoWatchPage {
       .then(seconds => parseInt(seconds, 10))
   }
 
-  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()
-      }
+  async pauseVideo (pauseAfterMs: number, isAutoplay: boolean, isSafari: boolean) {
+    if (isAutoplay === false) {
+      const playButton = element(by.css('.vjs-big-play-button'))
+      await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton))
+      await playButton.click()
+    }
+
+    if (isSafari === true) {
+      await browser.sleep(1000)
+      await element(by.css('.vjs-play-control')).click()
     }
 
+    await browser.sleep(1000)
     await browser.wait(browser.ExpectedConditions.invisibilityOf(element(by.css('.vjs-loading-spinner'))))
 
     const el = element(by.css('div.video-js'))
@@ -53,11 +58,7 @@ export class VideoWatchPage {
 
     await browser.sleep(pauseAfterMs)
 
-    if (isIphoneDevice === true) {
-      // document.webkitCancelFullScreen()
-    } else {
-      return el.click()
-    }
+    return el.click()
   }
 
   async clickOnVideo (videoName: string) {
@@ -69,7 +70,7 @@ export class VideoWatchPage {
   }
 
   async clickOnFirstVideo () {
-    const video = element(by.css('.videos .video-miniature:first-child .video-miniature-name'))
+    const video = element.all(by.css('.videos .video-miniature .video-miniature-name')).first()
     await browser.wait(browser.ExpectedConditions.elementToBeClickable(video))
     const textToReturn = video.getText()
 
@@ -79,7 +80,11 @@ export class VideoWatchPage {
     return textToReturn
   }
 
-  private getFirstVideoListSelector () {
-    return by.css('.videos .video-miniature-name')
+  async goOnAssociatedEmbed () {
+    let url = await browser.getCurrentUrl()
+    url = url.replace('/watch/', '/embed/')
+    url = url.replace(':3333', ':9001')
+
+    return browser.get(url)
   }
 }
index c21bc163ecc976cd5767427fe6f4bec432b67c35..f216f8dd18b4d805c91087af8ab1f31097522bbe 100644 (file)
@@ -10,6 +10,7 @@ describe('Videos workflow', () => {
   const videoName = new Date().getTime() + ' video'
   let isMobileDevice = false
   let isIphoneDevice = false
+  let isSafari = false
 
   beforeEach(async () => {
     browser.waitForAngularEnabled(false)
@@ -21,6 +22,7 @@ describe('Videos workflow', () => {
     const caps = await browser.getCapabilities()
     isMobileDevice = caps.get('realMobile') === 'true' || caps.get('realMobile') === true
     isIphoneDevice = caps.get('device') === 'iphone'
+    isSafari = caps.get('browserName') && caps.get('browserName').toLowerCase() === 'safari'
   })
 
   it('Should log in', () => {
@@ -38,14 +40,14 @@ describe('Videos workflow', () => {
       return
     }
 
-    pageUploadPage.navigateTo()
+    await pageUploadPage.navigateTo()
 
     await pageUploadPage.uploadVideo()
     return pageUploadPage.validSecondUploadStep(videoName)
   })
 
   it('Should list the video', async () => {
-    await videoWatchPage.goOnVideosList(isIphoneDevice)
+    await videoWatchPage.goOnVideosList(isIphoneDevice, isSafari)
 
     if (isMobileDevice) {
       console.log('Skipping because we are on a real device and BrowserStack does not support file upload.')
@@ -59,16 +61,21 @@ describe('Videos workflow', () => {
   it('Should go on video watch page', async () => {
     let videoNameToExcept = videoName
 
-    if (isMobileDevice && isIphoneDevice) videoNameToExcept = 'PeerTube_Mobile.v.1'
-
-    if (isMobileDevice && isIphoneDevice === false) videoNameToExcept = await videoWatchPage.clickOnFirstVideo()
+    if (isMobileDevice) videoNameToExcept = await videoWatchPage.clickOnFirstVideo()
     else await videoWatchPage.clickOnVideo(videoName)
 
     return videoWatchPage.waitWatchVideoName(videoNameToExcept)
   })
 
   it('Should play the video', async () => {
-    await videoWatchPage.pauseVideo(7000, isMobileDevice, isIphoneDevice)
+    await videoWatchPage.pauseVideo(7000, !isMobileDevice, isSafari)
+    expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
+  })
+
+  it('Should watch the associated embed video', async () => {
+    await videoWatchPage.goOnAssociatedEmbed()
+
+    await videoWatchPage.pauseVideo(7000, false, isSafari)
     expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
   })
 })
index 2e77a973fa7f5a2122c84309a9d0e9447e1f71d1..f419d58fc723528673788fc91bc96877d04367a2 100644 (file)
@@ -1,21 +1,5 @@
 import { VideoFile } from '../../../../shared/models/videos'
 
-import 'core-js/es6/symbol';
-import 'core-js/es6/object';
-import 'core-js/es6/function';
-import 'core-js/es6/parse-int';
-import 'core-js/es6/parse-float';
-import 'core-js/es6/number';
-import 'core-js/es6/math';
-import 'core-js/es6/string';
-import 'core-js/es6/date';
-import 'core-js/es6/array';
-import 'core-js/es6/regexp';
-import 'core-js/es6/map';
-import 'core-js/es6/weak-map';
-import 'core-js/es6/set';
-import 'core-js/es7/object';
-
 import 'videojs-hotkeys'
 import 'videojs-dock'
 import './peertube-link-button'
index 5789641fefff4d576604f3e16bdff86267812752..1e68100d1ddd325ba89f2b2516aff556c062a804 100644 (file)
@@ -4,7 +4,15 @@ import { VideoFile } from '../../../../shared/models/videos/video.model'
 import { renderVideo } from './video-renderer'
 import './settings-menu-button'
 import { PeertubePluginOptions, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
-import { getAverageBandwidth, getStoredMute, getStoredVolume, saveAverageBandwidth, saveMuteInStore, saveVolumeInStore } from './utils'
+import {
+  getAverageBandwidth,
+  getStoredMute,
+  getStoredVolume,
+  isMobile,
+  saveAverageBandwidth,
+  saveMuteInStore,
+  saveVolumeInStore
+} from './utils'
 import minBy from 'lodash-es/minBy'
 import maxBy from 'lodash-es/maxBy'
 import * as CacheChunkStore from 'cache-chunk-store'
@@ -262,7 +270,6 @@ class PeerTubePlugin extends Plugin {
 
   private tryToPlay (done?: Function) {
     if (!done) done = function () { /* empty */ }
-
     const playPromise = this.player.play()
     if (playPromise !== undefined) {
       return playPromise.then(done)
@@ -348,6 +355,9 @@ class PeerTubePlugin extends Plugin {
       // Proxy first play
       const oldPlay = this.player.play.bind(this.player)
       this.player.play = () => {
+        // Avoid issue new play policy on mobiles
+        if (isMobile()) oldPlay()
+
         this.player.addClass('vjs-has-big-play-button-clicked')
         this.player.play = oldPlay
 
index f5407ef60d5a5e0c95f8f0dc33451a378616d788..1df39d4e4a840ad4811062d8f594e917478a711d 100644 (file)
@@ -60,6 +60,10 @@ function saveAverageBandwidth (value: number) {
   return setLocalStorage('average-bandwidth', value.toString())
 }
 
+function isMobile () {
+  return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent)
+}
+
 export {
   toTitleCase,
   getStoredVolume,
@@ -68,6 +72,7 @@ export {
   getAverageBandwidth,
   saveMuteInStore,
   getStoredMute,
+  isMobile,
   bytes
 }
 
index c882192423f196a5e95f012bc6c240100ec38a26..ba906cc3215dd7e0fddd506d98a57456515c28e3 100644 (file)
@@ -1,5 +1,20 @@
 import './embed.scss'
 
+import 'core-js/es6/symbol'
+import 'core-js/es6/object'
+import 'core-js/es6/function'
+import 'core-js/es6/parse-int'
+import 'core-js/es6/parse-float'
+import 'core-js/es6/number'
+import 'core-js/es6/math'
+import 'core-js/es6/string'
+import 'core-js/es6/date'
+import 'core-js/es6/array'
+import 'core-js/es6/regexp'
+import 'core-js/es6/map'
+import 'core-js/es6/weak-map'
+import 'core-js/es6/set'
+
 // For google bot that uses Chrome 41 and does not understand fetch
 import 'whatwg-fetch'
 
index 16ef248e2986ac71cb1f19924445b32d49c827bf..9ed15982aa95e5bca41af96bb0f24eb8c9866291 100644 (file)
@@ -89,7 +89,7 @@
     "jsonld": "^1.0.1",
     "jsonld-signatures": "https://github.com/Chocobozzz/jsonld-signatures#rsa2017",
     "kue": "^0.11.6",
-    "lodash": "^4.11.1",
+    "lodash": "^4.17.10",
     "magnet-uri": "^5.1.4",
     "mkdirp": "^0.5.1",
     "morgan": "^1.5.3",
index 17c8f68efda0063b187cd400fa83a96475680ed2..0e70e6e51f835ac7cc2f8f794570bc7bd0d6b6cd 100755 (executable)
@@ -7,6 +7,7 @@ npm run clean:server:test
 (
     cd client
     npm run webdriver-manager update
+    npm run webpack -- --config webpack/webpack.video-embed.js --mode development
 )
 
 concurrently -k -s first \