diff options
-rw-r--r-- | client/e2e/fixtures/video.mp4 | bin | 38783 -> 619469 bytes | |||
-rw-r--r-- | client/e2e/protractor.conf.js | 35 | ||||
-rw-r--r-- | client/e2e/src/app.e2e-spec.ts | 14 | ||||
-rw-r--r-- | client/e2e/src/po/app.po.ts | 12 | ||||
-rw-r--r-- | client/e2e/src/po/login.po.ts | 6 | ||||
-rw-r--r-- | client/e2e/src/po/video-upload.po.ts | 4 | ||||
-rw-r--r-- | client/e2e/src/po/video-watch.po.ts | 46 | ||||
-rw-r--r-- | client/e2e/src/videos.e2e-spec.ts | 38 | ||||
-rwxr-xr-x | scripts/e2e.sh | 2 | ||||
-rw-r--r-- | server/tests/api/fixtures/video_too_long.webm | bin | 881903 -> 0 bytes |
10 files changed, 105 insertions, 52 deletions
diff --git a/client/e2e/fixtures/video.mp4 b/client/e2e/fixtures/video.mp4 index 35678362b..f9c9e2dd6 100644 --- a/client/e2e/fixtures/video.mp4 +++ b/client/e2e/fixtures/video.mp4 | |||
Binary files 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 @@ | |||
4 | const {SpecReporter} = require('jasmine-spec-reporter') | 4 | const {SpecReporter} = require('jasmine-spec-reporter') |
5 | 5 | ||
6 | exports.config = { | 6 | exports.config = { |
7 | allScriptsTimeout: 11000, | 7 | allScriptsTimeout: 25000, |
8 | specs: [ | 8 | specs: [ |
9 | './src/**/*.e2e-spec.ts' | 9 | './src/**/*.e2e-spec.ts' |
10 | ], | 10 | ], |
@@ -23,12 +23,6 @@ exports.config = { | |||
23 | version: '66' | 23 | version: '66' |
24 | }, | 24 | }, |
25 | { | 25 | { |
26 | browserName: 'Chrome', | ||
27 | version: '66', | ||
28 | os: 'android', | ||
29 | |||
30 | }, | ||
31 | { | ||
32 | browserName: 'Safari', | 26 | browserName: 'Safari', |
33 | version: '11.1' | 27 | version: '11.1' |
34 | }, | 28 | }, |
@@ -42,16 +36,35 @@ exports.config = { | |||
42 | }, | 36 | }, |
43 | { | 37 | { |
44 | browserName: 'Edge', | 38 | browserName: 'Edge', |
45 | version: '17' | 39 | version: '16' |
46 | } | 40 | }, |
41 | { | ||
42 | browserName: 'Chrome', | ||
43 | device: 'Google Nexus 6', | ||
44 | realMobile: 'true', | ||
45 | os_version: '5.0' | ||
46 | }, | ||
47 | // { | ||
48 | // browserName: 'Safari', | ||
49 | // device: 'iPhone 6s', | ||
50 | // realMobile: 'true', | ||
51 | // os_version: '9.0' | ||
52 | // }, | ||
53 | // { | ||
54 | // browserName: 'Safari', | ||
55 | // device: 'iPhone SE', | ||
56 | // realMobile: 'true', | ||
57 | // os_version: '11.2' | ||
58 | // } | ||
47 | ], | 59 | ], |
48 | 60 | ||
49 | maxSessions: 1, | 61 | maxSessions: 1, |
50 | baseUrl: 'http://localhost:4200/', | 62 | // BrowserStack compatible ports: https://www.browserstack.com/question/664 |
63 | baseUrl: 'http://localhost:3333/', | ||
51 | framework: 'jasmine', | 64 | framework: 'jasmine', |
52 | jasmineNodeOpts: { | 65 | jasmineNodeOpts: { |
53 | showColors: true, | 66 | showColors: true, |
54 | defaultTimeoutInterval: 30000, | 67 | defaultTimeoutInterval: 45000, |
55 | print: function () {} | 68 | print: function () {} |
56 | }, | 69 | }, |
57 | 70 | ||
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 @@ | |||
1 | import { AppPage } from './po/app.po' | ||
2 | |||
3 | describe('PeerTube app', () => { | ||
4 | let page: AppPage | ||
5 | |||
6 | beforeEach(() => { | ||
7 | page = new AppPage() | ||
8 | }) | ||
9 | |||
10 | it('Should display the app title', () => { | ||
11 | page.navigateTo() | ||
12 | expect(page.getHeaderTitle()).toEqual('PeerTube') | ||
13 | }) | ||
14 | }) | ||
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 @@ | |||
1 | import { browser, by, element } from 'protractor' | ||
2 | |||
3 | export class AppPage { | ||
4 | navigateTo () { | ||
5 | browser.waitForAngularEnabled(false) | ||
6 | return browser.get('/') | ||
7 | } | ||
8 | |||
9 | getHeaderTitle () { | ||
10 | return element(by.css('.instance-name')).getText() | ||
11 | } | ||
12 | } | ||
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 { | |||
4 | async loginAsRootUser () { | 4 | async loginAsRootUser () { |
5 | await browser.get('/login') | 5 | await browser.get('/login') |
6 | 6 | ||
7 | await element(by.css('input#username')).sendKeys('root') | 7 | element(by.css('input#username')).sendKeys('root') |
8 | await element(by.css('input#password')).sendKeys('test1') | 8 | element(by.css('input#password')).sendKeys('test1') |
9 | |||
10 | await browser.sleep(1000) | ||
9 | 11 | ||
10 | await element(by.css('form input[type=submit]')).click() | 12 | await element(by.css('form input[type=submit]')).click() |
11 | 13 | ||
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 @@ | |||
1 | import { browser, element, by } from 'protractor' | 1 | import { browser, by, element } from 'protractor' |
2 | import { join } from 'path' | ||
3 | import { FileDetector } from 'selenium-webdriver/remote' | 2 | import { FileDetector } from 'selenium-webdriver/remote' |
3 | import { join } from 'path' | ||
4 | 4 | ||
5 | export class VideoUploadPage { | 5 | export class VideoUploadPage { |
6 | navigateTo () { | 6 | 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 @@ | |||
1 | import { by, element, browser } from 'protractor' | 1 | import { by, element, browser } from 'protractor' |
2 | 2 | ||
3 | export class VideoWatchPage { | 3 | export class VideoWatchPage { |
4 | async goOnRecentlyAdded () { | 4 | async goOnVideosList (isIphoneDevice: boolean) { |
5 | const url = '/videos/recently-added' | 5 | let url: string |
6 | |||
7 | if (isIphoneDevice === true) { | ||
8 | // Local testing is buggy :/ | ||
9 | url = 'https://peertube2.cpy.re/videos/local' | ||
10 | } else { | ||
11 | url = '/videos/recently-added' | ||
12 | } | ||
6 | 13 | ||
7 | await browser.get(url) | 14 | await browser.get(url) |
8 | return browser.wait(browser.ExpectedConditions.elementToBeClickable(element(this.getFirstVideoListSelector()))) | 15 | return browser.wait(browser.ExpectedConditions.elementToBeClickable(element(this.getFirstVideoListSelector()))) |
9 | } | 16 | } |
10 | 17 | ||
11 | getVideosListName () { | 18 | getVideosListName () { |
12 | return element.all(this.getFirstVideoListSelector()).getText() | 19 | return element.all(this.getFirstVideoListSelector()) |
20 | .getText() | ||
21 | .then((texts: any) => texts.map(t => t.trim())) | ||
13 | } | 22 | } |
14 | 23 | ||
15 | waitWatchVideoName (videoName: string) { | 24 | waitWatchVideoName (videoName: string) { |
@@ -24,7 +33,19 @@ export class VideoWatchPage { | |||
24 | .then(seconds => parseInt(seconds, 10)) | 33 | .then(seconds => parseInt(seconds, 10)) |
25 | } | 34 | } |
26 | 35 | ||
27 | async pauseVideo (pauseAfterMs: number) { | 36 | async pauseVideo (pauseAfterMs: number, isMobileDevice: boolean, isIphoneDevice: boolean) { |
37 | if (isMobileDevice === true) { | ||
38 | if (isIphoneDevice === false) { | ||
39 | const playButton = element(by.css('.vjs-big-play-button')) | ||
40 | await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton)) | ||
41 | await playButton.click() | ||
42 | } else { | ||
43 | const playButton = element(by.css('video')) | ||
44 | await browser.wait(browser.ExpectedConditions.elementToBeClickable(playButton)) | ||
45 | await playButton.click() | ||
46 | } | ||
47 | } | ||
48 | |||
28 | await browser.wait(browser.ExpectedConditions.invisibilityOf(element(by.css('.vjs-loading-spinner')))) | 49 | await browser.wait(browser.ExpectedConditions.invisibilityOf(element(by.css('.vjs-loading-spinner')))) |
29 | 50 | ||
30 | const el = element(by.css('div.video-js')) | 51 | const el = element(by.css('div.video-js')) |
@@ -32,15 +53,30 @@ export class VideoWatchPage { | |||
32 | 53 | ||
33 | await browser.sleep(pauseAfterMs) | 54 | await browser.sleep(pauseAfterMs) |
34 | 55 | ||
35 | return el.click() | 56 | if (isIphoneDevice === true) { |
57 | // document.webkitCancelFullScreen() | ||
58 | } else { | ||
59 | return el.click() | ||
60 | } | ||
36 | } | 61 | } |
37 | 62 | ||
38 | async clickOnVideo (videoName: string) { | 63 | async clickOnVideo (videoName: string) { |
39 | const video = element(by.css('.videos .video-miniature .video-thumbnail[title="' + videoName + '"]')) | 64 | const video = element(by.css('.videos .video-miniature .video-thumbnail[title="' + videoName + '"]')) |
65 | await browser.wait(browser.ExpectedConditions.elementToBeClickable(video)) | ||
66 | await video.click() | ||
67 | |||
68 | await browser.wait(browser.ExpectedConditions.urlContains('/watch/')) | ||
69 | } | ||
70 | |||
71 | async clickOnFirstVideo () { | ||
72 | const video = element(by.css('.videos .video-miniature:first-child .video-miniature-name')) | ||
73 | await browser.wait(browser.ExpectedConditions.elementToBeClickable(video)) | ||
74 | const textToReturn = video.getText() | ||
40 | 75 | ||
41 | await video.click() | 76 | await video.click() |
42 | 77 | ||
43 | await browser.wait(browser.ExpectedConditions.urlContains('/watch/')) | 78 | await browser.wait(browser.ExpectedConditions.urlContains('/watch/')) |
79 | return textToReturn | ||
44 | } | 80 | } |
45 | 81 | ||
46 | private getFirstVideoListSelector () { | 82 | 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', () => { | |||
8 | let pageUploadPage: VideoUploadPage | 8 | let pageUploadPage: VideoUploadPage |
9 | let loginPage: LoginPage | 9 | let loginPage: LoginPage |
10 | const videoName = new Date().getTime() + ' video' | 10 | const videoName = new Date().getTime() + ' video' |
11 | let isMobileDevice = false | ||
12 | let isIphoneDevice = false | ||
13 | |||
14 | beforeEach(async () => { | ||
15 | browser.waitForAngularEnabled(false) | ||
11 | 16 | ||
12 | beforeEach(() => { | ||
13 | videoWatchPage = new VideoWatchPage() | 17 | videoWatchPage = new VideoWatchPage() |
14 | pageUploadPage = new VideoUploadPage() | 18 | pageUploadPage = new VideoUploadPage() |
15 | loginPage = new LoginPage() | 19 | loginPage = new LoginPage() |
20 | |||
21 | const caps = await browser.getCapabilities() | ||
22 | isMobileDevice = caps.get('realMobile') === 'true' || caps.get('realMobile') === true | ||
23 | isIphoneDevice = caps.get('device') === 'iphone' | ||
16 | }) | 24 | }) |
17 | 25 | ||
18 | it('Should log in', () => { | 26 | it('Should log in', () => { |
27 | if (isMobileDevice) { | ||
28 | console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') | ||
29 | return | ||
30 | } | ||
31 | |||
19 | return loginPage.loginAsRootUser() | 32 | return loginPage.loginAsRootUser() |
20 | }) | 33 | }) |
21 | 34 | ||
22 | it('Should upload a video', async () => { | 35 | it('Should upload a video', async () => { |
36 | if (isMobileDevice) { | ||
37 | console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') | ||
38 | return | ||
39 | } | ||
40 | |||
23 | pageUploadPage.navigateTo() | 41 | pageUploadPage.navigateTo() |
24 | 42 | ||
25 | await pageUploadPage.uploadVideo() | 43 | await pageUploadPage.uploadVideo() |
@@ -27,20 +45,30 @@ describe('Videos workflow', () => { | |||
27 | }) | 45 | }) |
28 | 46 | ||
29 | it('Should list the video', async () => { | 47 | it('Should list the video', async () => { |
30 | await videoWatchPage.goOnRecentlyAdded() | 48 | await videoWatchPage.goOnVideosList(isIphoneDevice) |
49 | |||
50 | if (isMobileDevice) { | ||
51 | console.log('Skipping because we are on a real device and BrowserStack does not support file upload.') | ||
52 | return | ||
53 | } | ||
31 | 54 | ||
32 | const videoNames = videoWatchPage.getVideosListName() | 55 | const videoNames = videoWatchPage.getVideosListName() |
33 | expect(videoNames).toContain(videoName) | 56 | expect(videoNames).toContain(videoName) |
34 | }) | 57 | }) |
35 | 58 | ||
36 | it('Should go on video watch page', async () => { | 59 | it('Should go on video watch page', async () => { |
37 | await videoWatchPage.clickOnVideo(videoName) | 60 | let videoNameToExcept = videoName |
61 | |||
62 | if (isMobileDevice && isIphoneDevice) videoNameToExcept = 'PeerTube_Mobile.v.1' | ||
63 | |||
64 | if (isMobileDevice && isIphoneDevice === false) videoNameToExcept = await videoWatchPage.clickOnFirstVideo() | ||
65 | else await videoWatchPage.clickOnVideo(videoName) | ||
38 | 66 | ||
39 | return videoWatchPage.waitWatchVideoName(videoName) | 67 | return videoWatchPage.waitWatchVideoName(videoNameToExcept) |
40 | }) | 68 | }) |
41 | 69 | ||
42 | it('Should play the video', async () => { | 70 | it('Should play the video', async () => { |
43 | await videoWatchPage.pauseVideo(2500) | 71 | await videoWatchPage.pauseVideo(7000, isMobileDevice, isIphoneDevice) |
44 | expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) | 72 | expect(videoWatchPage.getWatchVideoPlayerCurrentTime()).toBeGreaterThanOrEqual(2) |
45 | }) | 73 | }) |
46 | }) | 74 | }) |
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 | |||
10 | ) | 10 | ) |
11 | 11 | ||
12 | concurrently -k -s first \ | 12 | concurrently -k -s first \ |
13 | "cd client && npm run ng -- e2e" \ | 13 | "cd client && npm run ng -- e2e --port 3333" \ |
14 | "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' npm start" | 14 | "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"log\": { \"level\": \"warning\" } }' npm start" |
15 | 15 | ||
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 --- a/server/tests/api/fixtures/video_too_long.webm +++ /dev/null | |||
Binary files differ | |||