Fix e2e tests
authorChocobozzz <me@florianbigard.com>
Thu, 23 Jan 2020 13:23:19 +0000 (14:23 +0100)
committerChocobozzz <me@florianbigard.com>
Thu, 23 Jan 2020 13:59:44 +0000 (14:59 +0100)
client/e2e/fixtures/video.mp4
client/e2e/src/po/app.po.ts [new file with mode: 0644]
client/e2e/src/videos.e2e-spec.ts
client/src/app/shared/rxjs/zone.ts [new file with mode: 0644]
client/src/app/shared/user-subscription/user-subscription.service.ts
client/src/app/shared/video-playlist/video-playlist.service.ts
scripts/e2e/local.sh
shared/extra-utils/videos/videos.ts

index f9c9e2dd6e80f3e4678c7f142a92cd63f236a58b..c9ba8fd04bd2c56cd726710859af83d84dc65fde 100644 (file)
Binary files a/client/e2e/fixtures/video.mp4 and b/client/e2e/fixtures/video.mp4 differ
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..a636e82
--- /dev/null
@@ -0,0 +1,21 @@
+import { browser, by, element } from 'protractor'
+
+export class AppPage {
+
+  async closeWelcomeModal () {
+    const firstHandle = await browser.getWindowHandle()
+
+    if (await element(by.css('.configure-instance-button')).isPresent() === false) return
+
+    await element(by.css('.configure-instance-button')).click()
+
+    await browser.switchTo().window(firstHandle)
+
+    await browser.refresh()
+
+    await element(by.css('.form-group-checkbox')).click()
+    await element(by.css('.action-button-cancel')).click()
+
+    await browser.switchTo().window(firstHandle)
+  }
+}
index 27706a5061d3cf913e1e0b0d8695467a5e2b0ba5..075add53155b678429383acff07cbc76b4db1356 100644 (file)
@@ -4,6 +4,7 @@ import { LoginPage } from './po/login.po'
 import { browser } from 'protractor'
 import { VideoUpdatePage } from './po/video-update.po'
 import { MyAccountPage } from './po/my-account'
+import { AppPage } from './po/app.po'
 
 async function skipIfUploadNotSupported () {
   if (await isMobileDevice() || await isSafari()) {
@@ -30,6 +31,7 @@ describe('Videos workflow', () => {
   let videoUpdatePage: VideoUpdatePage
   let myAccountPage: MyAccountPage
   let loginPage: LoginPage
+  let appPage: AppPage
 
   let videoName = new Date().getTime() + ' video'
   const video2Name = new Date().getTime() + ' second video'
@@ -42,6 +44,7 @@ describe('Videos workflow', () => {
     videoUpdatePage = new VideoUpdatePage()
     myAccountPage = new MyAccountPage()
     loginPage = new LoginPage()
+    appPage = new AppPage()
 
     if (await isMobileDevice()) {
       console.log('Mobile device detected.')
@@ -61,6 +64,12 @@ describe('Videos workflow', () => {
     return loginPage.loginAsRootUser()
   })
 
+  it('Should close the welcome modal', async () => {
+    if (await skipIfUploadNotSupported()) return
+
+    await appPage.closeWelcomeModal()
+  })
+
   it('Should upload a video', async () => {
     if (await skipIfUploadNotSupported()) return
 
diff --git a/client/src/app/shared/rxjs/zone.ts b/client/src/app/shared/rxjs/zone.ts
new file mode 100644 (file)
index 0000000..74eed70
--- /dev/null
@@ -0,0 +1,40 @@
+import { SchedulerLike, Subscription } from 'rxjs'
+import { NgZone } from '@angular/core'
+
+class LeaveZoneScheduler implements SchedulerLike {
+  constructor (private zone: NgZone, private scheduler: SchedulerLike) {
+  }
+
+  schedule (...args: any[]): Subscription {
+    return this.zone.runOutsideAngular(() =>
+      this.scheduler.schedule.apply(this.scheduler, args)
+    )
+  }
+
+  now (): number {
+    return this.scheduler.now()
+  }
+}
+
+class EnterZoneScheduler implements SchedulerLike {
+  constructor (private zone: NgZone, private scheduler: SchedulerLike) {
+  }
+
+  schedule (...args: any[]): Subscription {
+    return this.zone.run(() =>
+      this.scheduler.schedule.apply(this.scheduler, args)
+    )
+  }
+
+  now (): number {
+    return this.scheduler.now()
+  }
+}
+
+export function leaveZone (zone: NgZone, scheduler: SchedulerLike): SchedulerLike {
+  return new LeaveZoneScheduler(zone, scheduler)
+}
+
+export function enterZone (zone: NgZone, scheduler: SchedulerLike): SchedulerLike {
+  return new EnterZoneScheduler(zone, scheduler)
+}
index bfb5848bc212b4df232298fb2abaff4d38e16a4f..9af9ba23e73a747897ea1a0996b92ae9563af059 100644 (file)
@@ -1,7 +1,7 @@
-import { bufferTime, catchError, filter, map, tap, share, switchMap } from 'rxjs/operators'
-import { Observable, ReplaySubject, Subject, of, merge } from 'rxjs'
+import { bufferTime, catchError, filter, map, observeOn, share, switchMap, tap } from 'rxjs/operators'
+import { asyncScheduler, merge, Observable, of, ReplaySubject, Subject } from 'rxjs'
 import { HttpClient, HttpParams } from '@angular/common/http'
-import { Injectable } from '@angular/core'
+import { Injectable, NgZone } from '@angular/core'
 import { ResultList } from '../../../../../shared'
 import { environment } from '../../../environments/environment'
 import { RestExtractor, RestService } from '../rest'
@@ -11,6 +11,7 @@ import { VideoChannel as VideoChannelServer } from '../../../../../shared/models
 import { ComponentPaginationLight } from '@app/shared/rest/component-pagination.model'
 import { uniq } from 'lodash-es'
 import * as debug from 'debug'
+import { enterZone, leaveZone } from '@app/shared/rxjs/zone'
 
 const logger = debug('peertube:subscriptions:UserSubscriptionService')
 
@@ -32,13 +33,16 @@ export class UserSubscriptionService {
   constructor (
     private authHttp: HttpClient,
     private restExtractor: RestExtractor,
-    private restService: RestService
+    private restService: RestService,
+    private ngZone: NgZone
   ) {
     this.existsObservable = merge(
       this.existsSubject.pipe(
-        bufferTime(500),
+        // We leave Angular zone so Protractor does not get stuck
+        bufferTime(500, leaveZone(this.ngZone, asyncScheduler)),
         filter(uris => uris.length !== 0),
         map(uris => uniq(uris)),
+        observeOn(enterZone(this.ngZone, asyncScheduler)),
         switchMap(uris => this.doSubscriptionsExist(uris)),
         share()
       ),
index fc5eb5337e518a8278747acfee6a2988cbca9bf2..bae6f9e04f24c93f56ebc3eef5eae956962f7c29 100644 (file)
@@ -1,6 +1,6 @@
-import { bufferTime, catchError, filter, map, share, switchMap, tap } from 'rxjs/operators'
-import { Injectable } from '@angular/core'
-import { merge, Observable, of, ReplaySubject, Subject } from 'rxjs'
+import { bufferTime, catchError, filter, map, observeOn, share, switchMap, tap } from 'rxjs/operators'
+import { Injectable, NgZone } from '@angular/core'
+import { asyncScheduler, merge, Observable, of, ReplaySubject, Subject } from 'rxjs'
 import { RestExtractor } from '../rest/rest-extractor.service'
 import { HttpClient, HttpParams } from '@angular/common/http'
 import { ResultList, VideoPlaylistElementCreate, VideoPlaylistElementUpdate } from '../../../../../shared'
@@ -23,6 +23,7 @@ import { VideoPlaylistElement as ServerVideoPlaylistElement } from '@shared/mode
 import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-element.model'
 import { uniq } from 'lodash-es'
 import * as debug from 'debug'
+import { enterZone, leaveZone } from '@app/shared/rxjs/zone'
 
 const logger = debug('peertube:playlists:VideoPlaylistService')
 
@@ -49,13 +50,16 @@ export class VideoPlaylistService {
     private authHttp: HttpClient,
     private serverService: ServerService,
     private restExtractor: RestExtractor,
-    private restService: RestService
+    private restService: RestService,
+    private ngZone: NgZone
   ) {
     this.videoExistsInPlaylistObservable = merge(
       this.videoExistsInPlaylistNotifier.pipe(
-        bufferTime(500),
+        // We leave Angular zone so Protractor does not get stuck
+        bufferTime(500, leaveZone(this.ngZone, asyncScheduler)),
         filter(videoIds => videoIds.length !== 0),
         map(videoIds => uniq(videoIds)),
+        observeOn(enterZone(this.ngZone, asyncScheduler)),
         switchMap(videoIds => this.doVideosExistInPlaylist(videoIds)),
         share()
       ),
index b883ccaa3a338bbd50dd5f6b7401a3a7c461a3d2..e8db2e808464d9a3f882fc469e9a47893a0d4de7 100755 (executable)
@@ -11,4 +11,4 @@ npm run clean:server:test
 
 npm run concurrently -- -k -s first \
     "cd client && npm run ng -- e2e --port 3333 -c local" \
-    "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' npm start"
+    "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' node dist/server"
index 9dec12703d0080720850288424e0788b01c19462..d1ac48292887fdb9b0edde0bac66572fe89a8ba9 100644 (file)
@@ -587,19 +587,17 @@ async function completeVideoCheck (
            'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')')
       .to.be.above(minSize).and.below(maxSize)
 
-    {
-      await testImage(url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath)
-    }
-
-    if (attributes.previewfile) {
-      await testImage(url, attributes.previewfile, videoDetails.previewPath)
-    }
-
     const torrent = await webtorrentAdd(file.magnetUri, true)
     expect(torrent.files).to.be.an('array')
     expect(torrent.files.length).to.equal(1)
     expect(torrent.files[0].path).to.exist.and.to.not.equal('')
   }
+
+  await testImage(url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath)
+
+  if (attributes.previewfile) {
+    await testImage(url, attributes.previewfile, videoDetails.previewPath)
+  }
 }
 
 async function videoUUIDToId (url: string, id: number | string) {