Add videos e2e tests
authorChocobozzz <me@florianbigard.com>
Thu, 17 May 2018 08:55:01 +0000 (10:55 +0200)
committerChocobozzz <me@florianbigard.com>
Thu, 17 May 2018 13:20:21 +0000 (15:20 +0200)
17 files changed:
README.md
client/e2e/fixtures/video.mp4 [new file with mode: 0644]
client/e2e/protractor.conf.js
client/e2e/src/app.e2e-spec.ts
client/e2e/src/app.po.ts [deleted file]
client/e2e/src/po/app.po.ts [new file with mode: 0644]
client/e2e/src/po/login.po.ts [new file with mode: 0644]
client/e2e/src/po/video-upload.po.ts [new file with mode: 0644]
client/e2e/src/po/video-watch.po.ts [new file with mode: 0644]
client/e2e/src/video-upload.e2e-spec.ts [deleted file]
client/e2e/src/video-upload.po.ts [deleted file]
client/e2e/src/video-watch.e2e-spec.ts [deleted file]
client/e2e/src/video-watch.po.ts [deleted file]
client/e2e/src/videos.e2e-spec.ts [new file with mode: 0644]
client/package.json
client/src/app/shared/video/video-miniature.component.html
scripts/e2e.sh

index 8abdaf67d458d43d76b975965f37edf82586df45..51c3747e8755546886d4eb2332260cebb52e7e3e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ donating to them](https://soutenir.framasoft.org/en/).**
   <a href="https://david-dm.org/Chocobozzz/PeerTube?path=client&type=dev">
     <img src="https://david-dm.org/Chocobozzz/PeerTube/dev-status.svg?path=client" alt="devDependency Status" />
   </a>
+  
+  <img src="http://lutim.cpy.re/js3rkfIc.png" alt="Browser Stack" />
 </p>
 
 <p align="center">
diff --git a/client/e2e/fixtures/video.mp4 b/client/e2e/fixtures/video.mp4
new file mode 100644 (file)
index 0000000..3567836
Binary files /dev/null and b/client/e2e/fixtures/video.mp4 differ
index 30705cb72e854ee0efcc4d3898b2cec147a310b3..932eaed51450057119173c846bd7017b4a103696 100644 (file)
@@ -8,9 +8,15 @@ exports.config = {
   specs: [
     './src/**/*.e2e-spec.ts'
   ],
-  capabilities: {
-    'browserName': 'chrome'
-  },
+  multiCapabilities: [
+    {
+      'browserName': 'firefox',
+      'moz:firefoxOptions': {
+        binary: 'firefox-developer'
+      }
+    }
+  ],
+  maxSessions: 1,
   directConnect: true,
   baseUrl: 'http://localhost:4200/',
   framework: 'jasmine',
index cdfd01f67d6983ee72b2bb8f89fd59ca1706e082..5b648207b49ba5cf626951d7a59e8ae5f502b75e 100644 (file)
@@ -1,4 +1,4 @@
-import { AppPage } from './app.po'
+import { AppPage } from './po/app.po'
 
 describe('PeerTube app', () => {
   let page: AppPage
@@ -7,7 +7,7 @@ describe('PeerTube app', () => {
     page = new AppPage()
   })
 
-  it('should display the app title', () => {
+  it('Should display the app title', () => {
     page.navigateTo()
     expect(page.getHeaderTitle()).toEqual('PeerTube')
   })
diff --git a/client/e2e/src/app.po.ts b/client/e2e/src/app.po.ts
deleted file mode 100644 (file)
index e3e293d..0000000
+++ /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/app.po.ts b/client/e2e/src/po/app.po.ts
new file mode 100644 (file)
index 0000000..e3e293d
--- /dev/null
@@ -0,0 +1,12 @@
+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
new file mode 100644 (file)
index 0000000..ada52cb
--- /dev/null
@@ -0,0 +1,14 @@
+import { browser, element, by } from 'protractor'
+
+export class LoginPage {
+  async loginAsRootUser () {
+    await browser.get('/login')
+
+    element(by.css('input#username')).sendKeys('root')
+    element(by.css('input#password')).sendKeys('test1')
+
+    await element(by.css('form input[type=submit]')).click()
+
+    return browser.wait(browser.ExpectedConditions.urlContains('/videos/'))
+  }
+}
diff --git a/client/e2e/src/po/video-upload.po.ts b/client/e2e/src/po/video-upload.po.ts
new file mode 100644 (file)
index 0000000..4f09bb2
--- /dev/null
@@ -0,0 +1,31 @@
+import { browser, element, by } from 'protractor'
+import { join } from 'path'
+
+export class VideoUploadPage {
+  navigateTo () {
+    return browser.get('/videos/upload')
+  }
+
+  async uploadVideo () {
+    const fileToUpload = join(__dirname, '../../fixtures/video.mp4')
+
+    await element(by.css('.upload-video-container input[type=file]')).sendKeys(fileToUpload)
+
+    // Wait for the upload to finish
+    await browser.wait(browser.ExpectedConditions.elementToBeClickable(this.getSecondStepSubmitButton()))
+  }
+
+  async validSecondUploadStep (videoName: string) {
+    const nameInput = element(by.css('input#name'))
+    await nameInput.clear()
+    await nameInput.sendKeys(videoName)
+
+    await this.getSecondStepSubmitButton().click()
+
+    return browser.wait(browser.ExpectedConditions.urlContains('/watch/'))
+  }
+
+  private getSecondStepSubmitButton () {
+    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
new file mode 100644 (file)
index 0000000..266c985
--- /dev/null
@@ -0,0 +1,45 @@
+import { by, element, browser } from 'protractor'
+
+export class VideoWatchPage {
+  async goOnRecentlyAdded () {
+    const url = '/videos/recently-added'
+
+    await browser.get(url)
+    return browser.wait(browser.ExpectedConditions.elementToBeClickable(element(this.getFirstVideoListSelector())))
+  }
+
+  getVideosListName () {
+    return element.all(this.getFirstVideoListSelector()).getText()
+  }
+
+  waitWatchVideoName (videoName: string) {
+    const elem = element(by.css('.video-info .video-info-name'))
+    return browser.wait(browser.ExpectedConditions.textToBePresentInElement(elem, videoName))
+  }
+
+  getWatchVideoPlayerCurrentTime () {
+    return element(by.css('.video-js .vjs-current-time-display'))
+      .getText()
+      .then((t: string) => t.split(':')[1])
+      .then(seconds => parseInt(seconds, 10))
+  }
+
+  async pauseVideo () {
+    const el = element(by.css('video'))
+    await browser.wait(browser.ExpectedConditions.elementToBeClickable(el))
+
+    return el.click()
+  }
+
+  async clickOnFirstVideoOfList () {
+    const video = element(by.css('.videos .video-miniature:first-child .video-thumbnail'))
+
+    await video.click()
+
+    await browser.wait(browser.ExpectedConditions.urlContains('/watch/'))
+  }
+
+  private getFirstVideoListSelector () {
+    return by.css('.videos .video-miniature-name')
+  }
+}
diff --git a/client/e2e/src/video-upload.e2e-spec.ts b/client/e2e/src/video-upload.e2e-spec.ts
deleted file mode 100644 (file)
index 45d8ae2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-import { VideoUploadPage } from './video-upload.po'
-
-describe('Video upload', () => {
-  let page: VideoUploadPage
-
-  beforeEach(() => {
-    page = new VideoUploadPage()
-  })
-})
diff --git a/client/e2e/src/video-upload.po.ts b/client/e2e/src/video-upload.po.ts
deleted file mode 100644 (file)
index df358e4..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-import { browser } from 'protractor'
-
-export class VideoUploadPage {
-  navigateTo () {
-    return browser.get('/videos/upload')
-  }
-}
diff --git a/client/e2e/src/video-watch.e2e-spec.ts b/client/e2e/src/video-watch.e2e-spec.ts
deleted file mode 100644 (file)
index be3552d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-import { VideoWatchPage } from './video-watch.po'
-
-describe('Video watch', () => {
-  let page: VideoWatchPage
-
-  beforeEach(() => {
-    page = new VideoWatchPage()
-  })
-})
diff --git a/client/e2e/src/video-watch.po.ts b/client/e2e/src/video-watch.po.ts
deleted file mode 100644 (file)
index 3b5454b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-import { browser } from 'protractor'
-
-export class VideoWatchPage {
-  navigateTo () {
-    browser.waitForAngularEnabled(false)
-    return browser.get('/')
-  }
-}
diff --git a/client/e2e/src/videos.e2e-spec.ts b/client/e2e/src/videos.e2e-spec.ts
new file mode 100644 (file)
index 0000000..4205fd7
--- /dev/null
@@ -0,0 +1,48 @@
+import { VideoWatchPage } from './po/video-watch.po'
+import { VideoUploadPage } from './po/video-upload.po'
+import { LoginPage } from './po/login.po'
+import { browser } from 'protractor'
+
+describe('Videos workflow', () => {
+  let videoWatchPage: VideoWatchPage
+  let pageUploadPage: VideoUploadPage
+  let loginPage: LoginPage
+  const videoName = new Date().getTime() + ' video'
+
+  beforeEach(() => {
+    videoWatchPage = new VideoWatchPage()
+    pageUploadPage = new VideoUploadPage()
+    loginPage = new LoginPage()
+  })
+
+  it('Should log in', () => {
+    return loginPage.loginAsRootUser()
+  })
+
+  it('Should upload a video', async () => {
+    pageUploadPage.navigateTo()
+
+    await pageUploadPage.uploadVideo()
+    return pageUploadPage.validSecondUploadStep(videoName)
+  })
+
+  it('Should list the video', async () => {
+    await videoWatchPage.goOnRecentlyAdded()
+
+    const videoNames = videoWatchPage.getVideosListName()
+    expect(videoNames).toContain(videoName)
+  })
+
+  it('Should go on video watch page', async () => {
+    await videoWatchPage.clickOnFirstVideoOfList()
+
+    return videoWatchPage.waitWatchVideoName(videoName)
+  })
+
+  it('Should play the video', async () => {
+    await browser.sleep(4000)
+
+    await videoWatchPage.pauseVideo()
+    expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2)
+  })
+})
index b108b0d1185c9bf5d945586df77b2630251abce2..393a4b13472ad28880f5e28804d5af3897b7f9a6 100644 (file)
@@ -18,7 +18,8 @@
     "tslint": "tslint",
     "ng": "ng",
     "postinstall": "npm rebuild node-sass && node angular-cli-patch.js",
-    "webpack-bundle-analyzer": "webpack-bundle-analyzer"
+    "webpack-bundle-analyzer": "webpack-bundle-analyzer",
+    "webdriver-manager": "webdriver-manager"
   },
   "license": "GPLv3",
   "resolutions": {
index e26cb058ac107ce7a19c5fcbd1809a09789c7262..1725e9f5cbd73f00c218bc1e42d901df294db98d 100644 (file)
@@ -2,14 +2,12 @@
   <my-video-thumbnail [video]="video" [nsfw]="isVideoBlur()"></my-video-thumbnail>
 
   <div class="video-miniature-information">
-    <span class="video-miniature-name">
-      <a
-        class="video-miniature-name"
-        [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur() }"
-      >
-          {{ video.name }}
-      </a>
-    </span>
+    <a
+      class="video-miniature-name"
+      [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur() }"
+    >
+        {{ video.name }}
+    </a>
 
     <span class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
     <a class="video-miniature-account" [routerLink]="[ '/accounts', video.account.id ]">{{ video.by }}</a>
index b1e9245c1379ba32a6d4eeb7f7975d1a0ff9c69a..bdd0514866c7588bc85fbcf56a6eab6dde6d9b69 100755 (executable)
@@ -2,10 +2,14 @@
 
 set -eu
 
-#npm run build:server
 npm run clean:server:test
 
+(
+    cd client
+    npm run webdriver-manager update
+)
+
 concurrently -k -s first \
     "cd client && npm run ng -- e2e" \
-    "NODE_ENV=test NODE_APP_INSTANCE=1 npm start"
+    "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' npm start"