aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/e2e
diff options
context:
space:
mode:
Diffstat (limited to 'client/e2e')
-rw-r--r--client/e2e/src/po/admin-plugin.po.ts31
-rw-r--r--client/e2e/src/po/anonymous-settings.po.ts21
-rw-r--r--client/e2e/src/po/my-account.po.ts (renamed from client/e2e/src/po/my-account.ts)17
-rw-r--r--client/e2e/src/po/video-upload.po.ts27
-rw-r--r--client/e2e/src/po/video-watch.po.ts42
-rw-r--r--client/e2e/src/suites-all/videos.e2e-spec.ts2
-rw-r--r--client/e2e/src/suites-local/custom-server-defaults.e2e-spec.ts86
-rw-r--r--client/e2e/src/suites-local/plugins.e2e-spec.ts78
-rw-r--r--client/e2e/src/suites-local/user-settings.e2e-spec.ts82
-rw-r--r--client/e2e/src/suites-local/videos-list.e2e-spec.ts26
-rw-r--r--client/e2e/src/utils/elements.ts21
-rw-r--r--client/e2e/src/utils/hooks.ts72
-rw-r--r--client/e2e/src/utils/index.ts2
-rw-r--r--client/e2e/src/utils/server.ts63
-rw-r--r--client/e2e/wdio.browserstack.conf.ts7
-rw-r--r--client/e2e/wdio.local-test.conf.ts9
-rw-r--r--client/e2e/wdio.local.conf.ts13
17 files changed, 571 insertions, 28 deletions
diff --git a/client/e2e/src/po/admin-plugin.po.ts b/client/e2e/src/po/admin-plugin.po.ts
new file mode 100644
index 000000000..6a3f3cf28
--- /dev/null
+++ b/client/e2e/src/po/admin-plugin.po.ts
@@ -0,0 +1,31 @@
1import { browserSleep, go } from '../utils'
2
3export class AdminPluginPage {
4
5 async navigateToSearch () {
6 await go('/admin/plugins/search')
7
8 await $('my-plugin-search').waitForDisplayed()
9 }
10
11 async search (name: string) {
12 const input = $('.search-bar input')
13 await input.waitForDisplayed()
14 await input.clearValue()
15 await input.setValue(name)
16
17 await browserSleep(1000)
18 }
19
20 async installHelloWorld () {
21 $('.plugin-name=hello-world').waitForDisplayed()
22
23 await $('.card-body my-button[icon=cloud-download]').click()
24
25 const submitModalButton = $('.modal-content input[type=submit]')
26 await submitModalButton.waitForClickable()
27 await submitModalButton.click()
28
29 await $('.card-body my-edit-button').waitForDisplayed()
30 }
31}
diff --git a/client/e2e/src/po/anonymous-settings.po.ts b/client/e2e/src/po/anonymous-settings.po.ts
new file mode 100644
index 000000000..21216a8f2
--- /dev/null
+++ b/client/e2e/src/po/anonymous-settings.po.ts
@@ -0,0 +1,21 @@
1import { getCheckbox } from '../utils'
2
3export class AnonymousSettingsPage {
4
5 async openSettings () {
6 const link = await $$('.menu-link').filter(async i => {
7 return await i.getText() === 'My settings'
8 }).then(links => links[0])
9
10 await link.click()
11
12 await $('my-user-video-settings').waitForDisplayed()
13 }
14
15 async clickOnP2PCheckbox () {
16 const p2p = await getCheckbox('p2pEnabled')
17 await p2p.waitForClickable()
18
19 await p2p.click()
20 }
21}
diff --git a/client/e2e/src/po/my-account.ts b/client/e2e/src/po/my-account.po.ts
index b51614fd9..20dafbf06 100644
--- a/client/e2e/src/po/my-account.ts
+++ b/client/e2e/src/po/my-account.po.ts
@@ -1,4 +1,4 @@
1import { go } from '../utils' 1import { getCheckbox, go } from '../utils'
2 2
3export class MyAccountPage { 3export class MyAccountPage {
4 4
@@ -27,6 +27,21 @@ export class MyAccountPage {
27 await nsfw.scrollIntoView(false) // Avoid issues with fixed header on firefox 27 await nsfw.scrollIntoView(false) // Avoid issues with fixed header on firefox
28 await nsfw.selectByAttribute('value', newValue) 28 await nsfw.selectByAttribute('value', newValue)
29 29
30 await this.submitVideoSettings()
31 }
32
33 async clickOnP2PCheckbox () {
34 const p2p = await getCheckbox('p2pEnabled')
35
36 await p2p.waitForClickable()
37 await p2p.scrollIntoView(false) // Avoid issues with fixed header on firefox
38
39 await p2p.click()
40
41 await this.submitVideoSettings()
42 }
43
44 private async submitVideoSettings () {
30 const submit = $('my-user-video-settings input[type=submit]') 45 const submit = $('my-user-video-settings input[type=submit]')
31 await submit.scrollIntoView(false) 46 await submit.scrollIntoView(false)
32 await submit.click() 47 await submit.click()
diff --git a/client/e2e/src/po/video-upload.po.ts b/client/e2e/src/po/video-upload.po.ts
index dd437c390..38395ea2f 100644
--- a/client/e2e/src/po/video-upload.po.ts
+++ b/client/e2e/src/po/video-upload.po.ts
@@ -1,9 +1,12 @@
1import { join } from 'path' 1import { join } from 'path'
2import { clickOnCheckbox } from '../utils' 2import { getCheckbox, selectCustomSelect } from '../utils'
3 3
4export class VideoUploadPage { 4export class VideoUploadPage {
5 async navigateTo () { 5 async navigateTo () {
6 await $('.header .publish-button').click() 6 const publishButton = await $('.header .publish-button')
7
8 await publishButton.waitForClickable()
9 await publishButton.click()
7 10
8 await $('.upload-video-container').waitForDisplayed() 11 await $('.upload-video-container').waitForDisplayed()
9 } 12 }
@@ -24,15 +27,17 @@ export class VideoUploadPage {
24 27
25 // Wait for the upload to finish 28 // Wait for the upload to finish
26 await browser.waitUntil(async () => { 29 await browser.waitUntil(async () => {
27 const actionButton = this.getSecondStepSubmitButton().$('.action-button') 30 const warning = await $('=Publish will be available when upload is finished').isDisplayed()
31 const progress = await $('.progress-bar=100%').isDisplayed()
28 32
29 const klass = await actionButton.getAttribute('class') 33 return !warning && progress
30 return !klass.includes('disabled')
31 }) 34 })
32 } 35 }
33 36
34 setAsNSFW () { 37 async setAsNSFW () {
35 return clickOnCheckbox('nsfw') 38 const checkbox = await getCheckbox('nsfw')
39
40 return checkbox.click()
36 } 41 }
37 42
38 async validSecondUploadStep (videoName: string) { 43 async validSecondUploadStep (videoName: string) {
@@ -47,6 +52,14 @@ export class VideoUploadPage {
47 }) 52 })
48 } 53 }
49 54
55 setAsPublic () {
56 return selectCustomSelect('privacy', 'Public')
57 }
58
59 setAsPrivate () {
60 return selectCustomSelect('privacy', 'Private')
61 }
62
50 private getSecondStepSubmitButton () { 63 private getSecondStepSubmitButton () {
51 return $('.submit-container my-button') 64 return $('.submit-container my-button')
52 } 65 }
diff --git a/client/e2e/src/po/video-watch.po.ts b/client/e2e/src/po/video-watch.po.ts
index 41425f4d7..cecda3a8b 100644
--- a/client/e2e/src/po/video-watch.po.ts
+++ b/client/e2e/src/po/video-watch.po.ts
@@ -21,12 +21,41 @@ export class VideoWatchPage {
21 return this.getVideoNameElement().then(e => e.getText()) 21 return this.getVideoNameElement().then(e => e.getText())
22 } 22 }
23 23
24 getPrivacy () {
25 return $('.attribute-privacy .attribute-value').getText()
26 }
27
28 getLicence () {
29 return $('.attribute-licence .attribute-value').getText()
30 }
31
32 async isDownloadEnabled () {
33 await this.clickOnMoreDropdownIcon()
34
35 return $('.dropdown-item .icon-download').isExisting()
36 }
37
38 areCommentsEnabled () {
39 return $('my-video-comment-add').isExisting()
40 }
41
42 isPrivacyWarningDisplayed () {
43 return $('my-privacy-concerns').isDisplayed()
44 }
45
24 async goOnAssociatedEmbed () { 46 async goOnAssociatedEmbed () {
25 let url = await browser.getUrl() 47 let url = await browser.getUrl()
26 url = url.replace('/w/', '/videos/embed/') 48 url = url.replace('/w/', '/videos/embed/')
27 url = url.replace(':3333', ':9001') 49 url = url.replace(':3333', ':9001')
28 50
29 return go(url) 51 await go(url)
52 await $('.vjs-big-play-button').waitForDisplayed()
53 }
54
55 async isEmbedWarningDisplayed () {
56 const text = await $('.vjs-dock-description').getText()
57
58 return !!text.trim()
30 } 59 }
31 60
32 goOnP2PMediaLoaderEmbed () { 61 goOnP2PMediaLoaderEmbed () {
@@ -38,10 +67,8 @@ export class VideoWatchPage {
38 } 67 }
39 68
40 async clickOnUpdate () { 69 async clickOnUpdate () {
41 const dropdown = $('my-video-actions-dropdown .action-button') 70 await this.clickOnMoreDropdownIcon()
42 await dropdown.click()
43 71
44 await $('.dropdown-menu.show .dropdown-item').waitForDisplayed()
45 const items = await $$('.dropdown-menu.show .dropdown-item') 72 const items = await $$('.dropdown-menu.show .dropdown-item')
46 73
47 for (const item of items) { 74 for (const item of items) {
@@ -86,6 +113,13 @@ export class VideoWatchPage {
86 }, { timeout: maxTime }) 113 }, { timeout: maxTime })
87 } 114 }
88 115
116 async clickOnMoreDropdownIcon () {
117 const dropdown = $('my-video-actions-dropdown .action-button')
118 await dropdown.click()
119
120 await $('.dropdown-menu.show .dropdown-item').waitForDisplayed()
121 }
122
89 private async getVideoNameElement () { 123 private async getVideoNameElement () {
90 // We have 2 video info name block, pick the first that is not empty 124 // We have 2 video info name block, pick the first that is not empty
91 const elem = async () => { 125 const elem = async () => {
diff --git a/client/e2e/src/suites-all/videos.e2e-spec.ts b/client/e2e/src/suites-all/videos.e2e-spec.ts
index 3b8305a25..b3a87c8e2 100644
--- a/client/e2e/src/suites-all/videos.e2e-spec.ts
+++ b/client/e2e/src/suites-all/videos.e2e-spec.ts
@@ -1,5 +1,5 @@
1import { LoginPage } from '../po/login.po' 1import { LoginPage } from '../po/login.po'
2import { MyAccountPage } from '../po/my-account' 2import { MyAccountPage } from '../po/my-account.po'
3import { PlayerPage } from '../po/player.po' 3import { PlayerPage } from '../po/player.po'
4import { VideoListPage } from '../po/video-list.po' 4import { VideoListPage } from '../po/video-list.po'
5import { VideoUpdatePage } from '../po/video-update.po' 5import { VideoUpdatePage } from '../po/video-update.po'
diff --git a/client/e2e/src/suites-local/custom-server-defaults.e2e-spec.ts b/client/e2e/src/suites-local/custom-server-defaults.e2e-spec.ts
new file mode 100644
index 000000000..e060d382f
--- /dev/null
+++ b/client/e2e/src/suites-local/custom-server-defaults.e2e-spec.ts
@@ -0,0 +1,86 @@
1import { LoginPage } from '../po/login.po'
2import { VideoUploadPage } from '../po/video-upload.po'
3import { VideoWatchPage } from '../po/video-watch.po'
4import { go, isMobileDevice, isSafari, waitServerUp } from '../utils'
5
6describe('Custom server defaults', () => {
7 let videoUploadPage: VideoUploadPage
8 let loginPage: LoginPage
9 let videoWatchPage: VideoWatchPage
10
11 before(async () => {
12 await waitServerUp()
13
14 loginPage = new LoginPage()
15 videoUploadPage = new VideoUploadPage()
16 videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
17
18 await browser.maximizeWindow()
19 })
20
21 describe('Publish default values', function () {
22 before(async function () {
23 await loginPage.loginAsRootUser()
24 })
25
26 it('Should upload a video with custom default values', async function () {
27 await videoUploadPage.navigateTo()
28 await videoUploadPage.uploadVideo()
29 await videoUploadPage.validSecondUploadStep('video')
30
31 await videoWatchPage.waitWatchVideoName('video')
32
33 expect(await videoWatchPage.getPrivacy()).toBe('Internal')
34 expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial')
35 expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy()
36 expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy()
37 })
38
39 after(async function () {
40 await loginPage.logout()
41 })
42 })
43
44 describe('P2P', function () {
45 let videoUrl: string
46
47 async function goOnVideoWatchPage () {
48 await go(videoUrl)
49 await videoWatchPage.waitWatchVideoName('video')
50 }
51
52 async function checkP2P (enabled: boolean) {
53 await goOnVideoWatchPage()
54 expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
55
56 await videoWatchPage.goOnAssociatedEmbed()
57 expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
58 }
59
60 before(async () => {
61 await loginPage.loginAsRootUser()
62 await videoUploadPage.navigateTo()
63 await videoUploadPage.uploadVideo()
64 await videoUploadPage.setAsPublic()
65 await videoUploadPage.validSecondUploadStep('video')
66
67 await videoWatchPage.waitWatchVideoName('video')
68
69 videoUrl = await browser.getUrl()
70 })
71
72 beforeEach(async function () {
73 await goOnVideoWatchPage()
74 })
75
76 it('Should have P2P disabled for a logged in user', async function () {
77 await checkP2P(false)
78 })
79
80 it('Should have P2P disabled for anonymous users', async function () {
81 await loginPage.logout()
82
83 await checkP2P(false)
84 })
85 })
86})
diff --git a/client/e2e/src/suites-local/plugins.e2e-spec.ts b/client/e2e/src/suites-local/plugins.e2e-spec.ts
new file mode 100644
index 000000000..411f1d217
--- /dev/null
+++ b/client/e2e/src/suites-local/plugins.e2e-spec.ts
@@ -0,0 +1,78 @@
1import { AdminPluginPage } from '../po/admin-plugin.po'
2import { LoginPage } from '../po/login.po'
3import { VideoUploadPage } from '../po/video-upload.po'
4import { getCheckbox, waitServerUp } from '../utils'
5
6describe('Plugins', () => {
7 let videoUploadPage: VideoUploadPage
8 let loginPage: LoginPage
9 let adminPluginPage: AdminPluginPage
10
11 function getPluginCheckbox () {
12 return getCheckbox('hello-world-field-4')
13 }
14
15 async function expectSubmitState ({ disabled }: { disabled: boolean }) {
16 const disabledSubmit = await $('my-button .disabled')
17
18 if (disabled) expect(await disabledSubmit.isDisplayed()).toBeTruthy()
19 else expect(await disabledSubmit.isDisplayed()).toBeFalsy()
20 }
21
22 before(async () => {
23 await waitServerUp()
24 })
25
26 beforeEach(async () => {
27 loginPage = new LoginPage()
28 videoUploadPage = new VideoUploadPage()
29 adminPluginPage = new AdminPluginPage()
30
31 await browser.maximizeWindow()
32 })
33
34 it('Should install hello world plugin', async () => {
35 await loginPage.loginAsRootUser()
36
37 await adminPluginPage.navigateToSearch()
38 await adminPluginPage.search('hello-world')
39 await adminPluginPage.installHelloWorld()
40 await browser.refresh()
41 })
42
43 it('Should have checkbox in video edit page', async () => {
44 await videoUploadPage.navigateTo()
45 await videoUploadPage.uploadVideo()
46
47 await $('span=Super field 4 in main tab').waitForDisplayed()
48
49 const checkbox = await getPluginCheckbox()
50 expect(await checkbox.isDisplayed()).toBeTruthy()
51
52 await expectSubmitState({ disabled: true })
53 })
54
55 it('Should check the checkbox and be able to submit the video', async function () {
56 const checkbox = await getPluginCheckbox()
57 await checkbox.click()
58
59 await expectSubmitState({ disabled: false })
60 })
61
62 it('Should uncheck the checkbox and not be able to submit the video', async function () {
63 const checkbox = await getPluginCheckbox()
64 await checkbox.click()
65
66 await expectSubmitState({ disabled: true })
67
68 const error = await $('.form-error*=Should be enabled')
69
70 expect(await error.isDisplayed()).toBeTruthy()
71 })
72
73 it('Should change the privacy and should hide the checkbox', async function () {
74 await videoUploadPage.setAsPrivate()
75
76 await expectSubmitState({ disabled: false })
77 })
78})
diff --git a/client/e2e/src/suites-local/user-settings.e2e-spec.ts b/client/e2e/src/suites-local/user-settings.e2e-spec.ts
new file mode 100644
index 000000000..b87501cd1
--- /dev/null
+++ b/client/e2e/src/suites-local/user-settings.e2e-spec.ts
@@ -0,0 +1,82 @@
1import { AnonymousSettingsPage } from '../po/anonymous-settings.po'
2import { LoginPage } from '../po/login.po'
3import { MyAccountPage } from '../po/my-account.po'
4import { VideoUploadPage } from '../po/video-upload.po'
5import { VideoWatchPage } from '../po/video-watch.po'
6import { go, isMobileDevice, isSafari, waitServerUp } from '../utils'
7
8describe('User settings', () => {
9 let videoUploadPage: VideoUploadPage
10 let loginPage: LoginPage
11 let videoWatchPage: VideoWatchPage
12 let myAccountPage: MyAccountPage
13 let anonymousSettingsPage: AnonymousSettingsPage
14
15 before(async () => {
16 await waitServerUp()
17
18 loginPage = new LoginPage()
19 videoUploadPage = new VideoUploadPage()
20 videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
21 myAccountPage = new MyAccountPage()
22 anonymousSettingsPage = new AnonymousSettingsPage()
23
24 await browser.maximizeWindow()
25 })
26
27 describe('P2P', function () {
28 let videoUrl: string
29
30 async function goOnVideoWatchPage () {
31 await go(videoUrl)
32 await videoWatchPage.waitWatchVideoName('video')
33 }
34
35 async function checkP2P (enabled: boolean) {
36 await goOnVideoWatchPage()
37 expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
38
39 await videoWatchPage.goOnAssociatedEmbed()
40 expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
41 }
42
43 before(async () => {
44 await loginPage.loginAsRootUser()
45 await videoUploadPage.navigateTo()
46 await videoUploadPage.uploadVideo()
47 await videoUploadPage.validSecondUploadStep('video')
48
49 await videoWatchPage.waitWatchVideoName('video')
50
51 videoUrl = await browser.getUrl()
52 })
53
54 beforeEach(async function () {
55 await goOnVideoWatchPage()
56 })
57
58 it('Should have P2P enabled for a logged in user', async function () {
59 await checkP2P(true)
60 })
61
62 it('Should disable P2P for a logged in user', async function () {
63 await myAccountPage.navigateToMySettings()
64 await myAccountPage.clickOnP2PCheckbox()
65
66 await checkP2P(false)
67 })
68
69 it('Should have P2P enabled for anonymous users', async function () {
70 await loginPage.logout()
71
72 await checkP2P(true)
73 })
74
75 it('Should disable P2P for an anonymous user', async function () {
76 await anonymousSettingsPage.openSettings()
77 await anonymousSettingsPage.clickOnP2PCheckbox()
78
79 await checkP2P(false)
80 })
81 })
82})
diff --git a/client/e2e/src/suites-local/videos-list.e2e-spec.ts b/client/e2e/src/suites-local/videos-list.e2e-spec.ts
index 1e0a88859..ce57261b9 100644
--- a/client/e2e/src/suites-local/videos-list.e2e-spec.ts
+++ b/client/e2e/src/suites-local/videos-list.e2e-spec.ts
@@ -1,9 +1,10 @@
1import { AdminConfigPage } from '../po/admin-config.po' 1import { AdminConfigPage } from '../po/admin-config.po'
2import { LoginPage } from '../po/login.po' 2import { LoginPage } from '../po/login.po'
3import { MyAccountPage } from '../po/my-account' 3import { MyAccountPage } from '../po/my-account.po'
4import { VideoListPage } from '../po/video-list.po' 4import { VideoListPage } from '../po/video-list.po'
5import { VideoSearchPage } from '../po/video-search.po' 5import { VideoSearchPage } from '../po/video-search.po'
6import { VideoUploadPage } from '../po/video-upload.po' 6import { VideoUploadPage } from '../po/video-upload.po'
7import { VideoWatchPage } from '../po/video-watch.po'
7import { NSFWPolicy } from '../types/common' 8import { NSFWPolicy } from '../types/common'
8import { isMobileDevice, isSafari, waitServerUp } from '../utils' 9import { isMobileDevice, isSafari, waitServerUp } from '../utils'
9 10
@@ -14,6 +15,7 @@ describe('Videos list', () => {
14 let loginPage: LoginPage 15 let loginPage: LoginPage
15 let myAccountPage: MyAccountPage 16 let myAccountPage: MyAccountPage
16 let videoSearchPage: VideoSearchPage 17 let videoSearchPage: VideoSearchPage
18 let videoWatchPage: VideoWatchPage
17 19
18 const seed = Math.random() 20 const seed = Math.random()
19 const nsfwVideo = seed + ' - nsfw' 21 const nsfwVideo = seed + ' - nsfw'
@@ -108,6 +110,7 @@ describe('Videos list', () => {
108 videoUploadPage = new VideoUploadPage() 110 videoUploadPage = new VideoUploadPage()
109 myAccountPage = new MyAccountPage() 111 myAccountPage = new MyAccountPage()
110 videoSearchPage = new VideoSearchPage() 112 videoSearchPage = new VideoSearchPage()
113 videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
111 114
112 await browser.maximizeWindow() 115 await browser.maximizeWindow()
113 }) 116 })
@@ -191,5 +194,26 @@ describe('Videos list', () => {
191 await checkCommonVideoListPages('display') 194 await checkCommonVideoListPages('display')
192 await checkSearchPage('display') 195 await checkSearchPage('display')
193 }) 196 })
197
198 after(async () => {
199 await loginPage.logout()
200 })
201 })
202
203 describe('Default upload values', function () {
204
205 it('Should have default video values', async function () {
206 await loginPage.loginAsRootUser()
207 await videoUploadPage.navigateTo()
208 await videoUploadPage.uploadVideo()
209 await videoUploadPage.validSecondUploadStep('video')
210
211 await videoWatchPage.waitWatchVideoName('video')
212
213 expect(await videoWatchPage.getPrivacy()).toBe('Public')
214 expect(await videoWatchPage.getLicence()).toBe('Unknown')
215 expect(await videoWatchPage.isDownloadEnabled()).toBeTruthy()
216 expect(await videoWatchPage.areCommentsEnabled()).toBeTruthy()
217 })
194 }) 218 })
195}) 219})
diff --git a/client/e2e/src/utils/elements.ts b/client/e2e/src/utils/elements.ts
index cadc46cce..3ffa5defd 100644
--- a/client/e2e/src/utils/elements.ts
+++ b/client/e2e/src/utils/elements.ts
@@ -1,7 +1,22 @@
1function clickOnCheckbox (name: string) { 1function getCheckbox (name: string) {
2 return $(`my-peertube-checkbox[inputname=${name}] label`).click() 2 return $(`my-peertube-checkbox input[id=${name}]`).parentElement()
3}
4
5async function selectCustomSelect (id: string, valueLabel: string) {
6 await $(`[formcontrolname=${id}] .ng-arrow-wrapper`).click()
7
8 const option = await $$(`[formcontrolname=${id}] .ng-option`).filter(async o => {
9 const text = await o.getText()
10
11 return text.trimStart().startsWith(valueLabel)
12 }).then(options => options[0])
13
14 await option.waitForDisplayed()
15
16 return option.click()
3} 17}
4 18
5export { 19export {
6 clickOnCheckbox 20 getCheckbox,
21 selectCustomSelect
7} 22}
diff --git a/client/e2e/src/utils/hooks.ts b/client/e2e/src/utils/hooks.ts
new file mode 100644
index 000000000..e139d8183
--- /dev/null
+++ b/client/e2e/src/utils/hooks.ts
@@ -0,0 +1,72 @@
1import { ChildProcessWithoutNullStreams } from 'child_process'
2import { basename } from 'path'
3import { runCommand, runServer } from './server'
4
5let appInstance: string
6let app: ChildProcessWithoutNullStreams
7
8async function beforeLocalSuite (suite: any) {
9 const config = buildConfig(suite.file)
10
11 await runCommand('npm run clean:server:test -- ' + appInstance)
12 app = runServer(appInstance, config)
13}
14
15function afterLocalSuite () {
16 app.kill()
17 app = undefined
18}
19
20function beforeLocalSession (config: { baseUrl: string }, capabilities: { browserName: string }) {
21 appInstance = capabilities['browserName'] === 'chrome' ? '1' : '2'
22 config.baseUrl = 'http://localhost:900' + appInstance
23}
24
25async function onBrowserStackPrepare () {
26 const appInstance = '1'
27
28 await runCommand('npm run clean:server:test -- ' + appInstance)
29 app = runServer(appInstance)
30}
31
32function onBrowserStackComplete () {
33 app.kill()
34 app = undefined
35}
36
37export {
38 beforeLocalSession,
39 afterLocalSuite,
40 beforeLocalSuite,
41 onBrowserStackPrepare,
42 onBrowserStackComplete
43}
44
45// ---------------------------------------------------------------------------
46
47function buildConfig (suiteFile: string = undefined) {
48 const filename = basename(suiteFile)
49
50 if (filename === 'custom-server-defaults.e2e-spec.ts') {
51 return {
52 defaults: {
53 publish: {
54 download_enabled: false,
55 comments_enabled: false,
56 privacy: 4,
57 licence: 4
58 },
59 p2p: {
60 webapp: {
61 enabled: false
62 },
63 embed: {
64 enabled: false
65 }
66 }
67 }
68 }
69 }
70
71 return {}
72}
diff --git a/client/e2e/src/utils/index.ts b/client/e2e/src/utils/index.ts
index 5da1ad517..354352ee2 100644
--- a/client/e2e/src/utils/index.ts
+++ b/client/e2e/src/utils/index.ts
@@ -1,3 +1,5 @@
1export * from './common' 1export * from './common'
2export * from './elements' 2export * from './elements'
3export * from './hooks'
4export * from './server'
3export * from './urls' 5export * from './urls'
diff --git a/client/e2e/src/utils/server.ts b/client/e2e/src/utils/server.ts
new file mode 100644
index 000000000..7089a5c9c
--- /dev/null
+++ b/client/e2e/src/utils/server.ts
@@ -0,0 +1,63 @@
1import { exec, spawn } from 'child_process'
2import { join, resolve } from 'path'
3
4function runServer (appInstance: string, config: any = {}) {
5 const env = Object.create(process.env)
6 env['NODE_ENV'] = 'test'
7 env['NODE_APP_INSTANCE'] = appInstance
8
9 env['NODE_CONFIG'] = JSON.stringify({
10 rates_limit: {
11 api: {
12 max: 5000
13 },
14 login: {
15 max: 5000
16 }
17 },
18 log: {
19 level: 'warn'
20 },
21 signup: {
22 enabled: false
23 },
24 transcoding: {
25 enabled: false
26 },
27
28 ...config
29 })
30
31 const forkOptions = {
32 env,
33 cwd: getRootCWD(),
34 detached: false
35 }
36
37 const p = spawn('node', [ join('dist', 'server.js') ], forkOptions)
38 p.stderr.on('data', data => console.error(data.toString()))
39 p.stdout.on('data', data => console.error(data.toString()))
40
41 return p
42}
43
44function runCommand (command: string) {
45 return new Promise<void>((res, rej) => {
46 const p = exec(command, { cwd: getRootCWD() })
47
48 p.stderr.on('data', data => console.error(data.toString()))
49 p.on('error', err => rej(err))
50 p.on('exit', () => res())
51 })
52}
53
54export {
55 runServer,
56 runCommand
57}
58
59// ---------------------------------------------------------------------------
60
61function getRootCWD () {
62 return resolve('../..')
63}
diff --git a/client/e2e/wdio.browserstack.conf.ts b/client/e2e/wdio.browserstack.conf.ts
index 43614a862..b89cdbc2e 100644
--- a/client/e2e/wdio.browserstack.conf.ts
+++ b/client/e2e/wdio.browserstack.conf.ts
@@ -1,3 +1,4 @@
1import { onBrowserStackComplete, onBrowserStackPrepare } from './src/utils'
1import { config as mainConfig } from './wdio.main.conf' 2import { config as mainConfig } from './wdio.main.conf'
2 3
3const user = process.env.BROWSERSTACK_USER 4const user = process.env.BROWSERSTACK_USER
@@ -114,6 +115,10 @@ module.exports = {
114 if (capabilities['bstack:options'].realMobile === true) { 115 if (capabilities['bstack:options'].realMobile === true) {
115 capabilities['bstack:options'].local = false 116 capabilities['bstack:options'].local = false
116 } 117 }
117 } 118 },
119
120 onPrepare: onBrowserStackPrepare,
121 onComplete: onBrowserStackComplete
122
118 } as WebdriverIO.Config 123 } as WebdriverIO.Config
119} 124}
diff --git a/client/e2e/wdio.local-test.conf.ts b/client/e2e/wdio.local-test.conf.ts
index 32e6d340c..5389ebcf0 100644
--- a/client/e2e/wdio.local-test.conf.ts
+++ b/client/e2e/wdio.local-test.conf.ts
@@ -1,3 +1,4 @@
1import { afterLocalSuite, beforeLocalSuite, beforeLocalSession } from './src/utils'
1import { config as mainConfig } from './wdio.main.conf' 2import { config as mainConfig } from './wdio.main.conf'
2 3
3const prefs = { 4const prefs = {
@@ -21,12 +22,16 @@ module.exports = {
21 browserName: 'chrome', 22 browserName: 'chrome',
22 acceptInsecureCerts: true, 23 acceptInsecureCerts: true,
23 'goog:chromeOptions': { 24 'goog:chromeOptions': {
24 args: [ '--headless', '--disable-gpu', '--window-size=1280,1024' ], 25 args: [ '--disable-gpu', '--window-size=1280,1024' ],
25 prefs 26 prefs
26 } 27 }
27 } 28 }
28 ], 29 ],
29 30
30 services: [ 'chromedriver' ] 31 services: [ 'chromedriver' ],
32
33 beforeSession: beforeLocalSession,
34 beforeSuite: beforeLocalSuite,
35 afterSuite: afterLocalSuite
31 } as WebdriverIO.Config 36 } as WebdriverIO.Config
32} 37}
diff --git a/client/e2e/wdio.local.conf.ts b/client/e2e/wdio.local.conf.ts
index 43b820ca6..d02679e06 100644
--- a/client/e2e/wdio.local.conf.ts
+++ b/client/e2e/wdio.local.conf.ts
@@ -1,3 +1,4 @@
1import { afterLocalSuite, beforeLocalSession, beforeLocalSuite } from './src/utils'
1import { config as mainConfig } from './wdio.main.conf' 2import { config as mainConfig } from './wdio.main.conf'
2 3
3const prefs = { 4const prefs = {
@@ -11,7 +12,7 @@ module.exports = {
11 12
12 runner: 'local', 13 runner: 'local',
13 14
14 maxInstances: 2, 15 maxInstancesPerCapability: 1,
15 16
16 capabilities: [ 17 capabilities: [
17 { 18 {
@@ -34,12 +35,8 @@ module.exports = {
34 35
35 services: [ 'chromedriver', 'geckodriver' ], 36 services: [ 'chromedriver', 'geckodriver' ],
36 37
37 beforeSession: function (config, capabilities) { 38 beforeSession: beforeLocalSession,
38 if (capabilities['browserName'] === 'chrome') { 39 beforeSuite: beforeLocalSuite,
39 config.baseUrl = 'http://localhost:9001' 40 afterSuite: afterLocalSuite
40 } else {
41 config.baseUrl = 'http://localhost:9002'
42 }
43 }
44 } as WebdriverIO.Config 41 } as WebdriverIO.Config
45} 42}