diff options
31 files changed, 467 insertions, 89 deletions
diff --git a/client/e2e/src/po/video-watch.po.ts b/client/e2e/src/po/video-watch.po.ts index 41425f4d7..1406c971a 100644 --- a/client/e2e/src/po/video-watch.po.ts +++ b/client/e2e/src/po/video-watch.po.ts | |||
@@ -21,6 +21,24 @@ 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 | |||
24 | async goOnAssociatedEmbed () { | 42 | async goOnAssociatedEmbed () { |
25 | let url = await browser.getUrl() | 43 | let url = await browser.getUrl() |
26 | url = url.replace('/w/', '/videos/embed/') | 44 | url = url.replace('/w/', '/videos/embed/') |
@@ -38,10 +56,8 @@ export class VideoWatchPage { | |||
38 | } | 56 | } |
39 | 57 | ||
40 | async clickOnUpdate () { | 58 | async clickOnUpdate () { |
41 | const dropdown = $('my-video-actions-dropdown .action-button') | 59 | await this.clickOnMoreDropdownIcon() |
42 | await dropdown.click() | ||
43 | 60 | ||
44 | await $('.dropdown-menu.show .dropdown-item').waitForDisplayed() | ||
45 | const items = await $$('.dropdown-menu.show .dropdown-item') | 61 | const items = await $$('.dropdown-menu.show .dropdown-item') |
46 | 62 | ||
47 | for (const item of items) { | 63 | for (const item of items) { |
@@ -86,6 +102,13 @@ export class VideoWatchPage { | |||
86 | }, { timeout: maxTime }) | 102 | }, { timeout: maxTime }) |
87 | } | 103 | } |
88 | 104 | ||
105 | async clickOnMoreDropdownIcon () { | ||
106 | const dropdown = $('my-video-actions-dropdown .action-button') | ||
107 | await dropdown.click() | ||
108 | |||
109 | await $('.dropdown-menu.show .dropdown-item').waitForDisplayed() | ||
110 | } | ||
111 | |||
89 | private async getVideoNameElement () { | 112 | private async getVideoNameElement () { |
90 | // We have 2 video info name block, pick the first that is not empty | 113 | // We have 2 video info name block, pick the first that is not empty |
91 | const elem = async () => { | 114 | const elem = async () => { |
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..c2c8edcc9 --- /dev/null +++ b/client/e2e/src/suites-local/custom-server-defaults.e2e-spec.ts | |||
@@ -0,0 +1,37 @@ | |||
1 | import { LoginPage } from '../po/login.po' | ||
2 | import { VideoUploadPage } from '../po/video-upload.po' | ||
3 | import { VideoWatchPage } from '../po/video-watch.po' | ||
4 | import { isMobileDevice, isSafari, waitServerUp } from '../utils' | ||
5 | |||
6 | describe('Custom server defaults', () => { | ||
7 | let videoUploadPage: VideoUploadPage | ||
8 | let loginPage: LoginPage | ||
9 | let videoWatchPage: VideoWatchPage | ||
10 | |||
11 | before(async () => { | ||
12 | await waitServerUp() | ||
13 | }) | ||
14 | |||
15 | beforeEach(async () => { | ||
16 | loginPage = new LoginPage() | ||
17 | videoUploadPage = new VideoUploadPage() | ||
18 | videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari()) | ||
19 | |||
20 | await browser.maximizeWindow() | ||
21 | }) | ||
22 | |||
23 | it('Should upload a video with custom default values', async function () { | ||
24 | await loginPage.loginAsRootUser() | ||
25 | await videoUploadPage.navigateTo() | ||
26 | await videoUploadPage.uploadVideo() | ||
27 | await videoUploadPage.validSecondUploadStep('video') | ||
28 | |||
29 | await videoWatchPage.waitWatchVideoName('video') | ||
30 | |||
31 | expect(await videoWatchPage.getPrivacy()).toBe('Internal') | ||
32 | expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial') | ||
33 | expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy() | ||
34 | expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy() | ||
35 | }) | ||
36 | |||
37 | }) | ||
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..bca6018b9 100644 --- a/client/e2e/src/suites-local/videos-list.e2e-spec.ts +++ b/client/e2e/src/suites-local/videos-list.e2e-spec.ts | |||
@@ -4,6 +4,7 @@ import { MyAccountPage } from '../po/my-account' | |||
4 | import { VideoListPage } from '../po/video-list.po' | 4 | import { VideoListPage } from '../po/video-list.po' |
5 | import { VideoSearchPage } from '../po/video-search.po' | 5 | import { VideoSearchPage } from '../po/video-search.po' |
6 | import { VideoUploadPage } from '../po/video-upload.po' | 6 | import { VideoUploadPage } from '../po/video-upload.po' |
7 | import { VideoWatchPage } from '../po/video-watch.po' | ||
7 | import { NSFWPolicy } from '../types/common' | 8 | import { NSFWPolicy } from '../types/common' |
8 | import { isMobileDevice, isSafari, waitServerUp } from '../utils' | 9 | import { 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/hooks.ts b/client/e2e/src/utils/hooks.ts new file mode 100644 index 000000000..e42c6a5d8 --- /dev/null +++ b/client/e2e/src/utils/hooks.ts | |||
@@ -0,0 +1,64 @@ | |||
1 | import { ChildProcessWithoutNullStreams } from 'child_process' | ||
2 | import { basename } from 'path' | ||
3 | import { runCommand, runServer } from './server' | ||
4 | |||
5 | let appInstance: string | ||
6 | let app: ChildProcessWithoutNullStreams | ||
7 | |||
8 | async 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 | |||
15 | function afterLocalSuite () { | ||
16 | app.kill() | ||
17 | app = undefined | ||
18 | } | ||
19 | |||
20 | function beforeLocalSession (config: { baseUrl: string }, capabilities: { browserName: string }) { | ||
21 | appInstance = capabilities['browserName'] === 'chrome' ? '1' : '2' | ||
22 | config.baseUrl = 'http://localhost:900' + appInstance | ||
23 | } | ||
24 | |||
25 | async function onBrowserStackPrepare () { | ||
26 | const appInstance = '1' | ||
27 | |||
28 | await runCommand('npm run clean:server:test -- ' + appInstance) | ||
29 | app = runServer(appInstance) | ||
30 | } | ||
31 | |||
32 | function onBrowserStackComplete () { | ||
33 | app.kill() | ||
34 | app = undefined | ||
35 | } | ||
36 | |||
37 | export { | ||
38 | beforeLocalSession, | ||
39 | afterLocalSuite, | ||
40 | beforeLocalSuite, | ||
41 | onBrowserStackPrepare, | ||
42 | onBrowserStackComplete | ||
43 | } | ||
44 | |||
45 | // --------------------------------------------------------------------------- | ||
46 | |||
47 | function 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 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | return {} | ||
64 | } | ||
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 @@ | |||
1 | export * from './common' | 1 | export * from './common' |
2 | export * from './elements' | 2 | export * from './elements' |
3 | export * from './hooks' | ||
4 | export * from './server' | ||
3 | export * from './urls' | 5 | export * 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 @@ | |||
1 | import { exec, spawn } from 'child_process' | ||
2 | import { join, resolve } from 'path' | ||
3 | |||
4 | function 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 | |||
44 | function 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 | |||
54 | export { | ||
55 | runServer, | ||
56 | runCommand | ||
57 | } | ||
58 | |||
59 | // --------------------------------------------------------------------------- | ||
60 | |||
61 | function 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 @@ | |||
1 | import { onBrowserStackComplete, onBrowserStackPrepare } from './src/utils' | ||
1 | import { config as mainConfig } from './wdio.main.conf' | 2 | import { config as mainConfig } from './wdio.main.conf' |
2 | 3 | ||
3 | const user = process.env.BROWSERSTACK_USER | 4 | const 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 @@ | |||
1 | import { afterLocalSuite, beforeLocalSuite, beforeLocalSession } from './src/utils' | ||
1 | import { config as mainConfig } from './wdio.main.conf' | 2 | import { config as mainConfig } from './wdio.main.conf' |
2 | 3 | ||
3 | const prefs = { | 4 | const 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 @@ | |||
1 | import { afterLocalSuite, beforeLocalSession, beforeLocalSuite } from './src/utils' | ||
1 | import { config as mainConfig } from './wdio.main.conf' | 2 | import { config as mainConfig } from './wdio.main.conf' |
2 | 3 | ||
3 | const prefs = { | 4 | const 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 | } |
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts index 39767f258..2bec933e9 100644 --- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts | |||
@@ -110,9 +110,10 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
110 | updateForm () { | 110 | updateForm () { |
111 | const defaultValues: any = { | 111 | const defaultValues: any = { |
112 | nsfw: 'false', | 112 | nsfw: 'false', |
113 | commentsEnabled: 'true', | 113 | commentsEnabled: this.serverConfig.defaults.publish.commentsEnabled, |
114 | downloadEnabled: 'true', | 114 | downloadEnabled: this.serverConfig.defaults.publish.downloadEnabled, |
115 | waitTranscoding: 'true', | 115 | waitTranscoding: 'true', |
116 | licence: this.serverConfig.defaults.publish.licence, | ||
116 | tags: [] | 117 | tags: [] |
117 | } | 118 | } |
118 | const obj: any = { | 119 | const obj: any = { |
@@ -160,6 +161,8 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
160 | } | 161 | } |
161 | 162 | ||
162 | ngOnInit () { | 163 | ngOnInit () { |
164 | this.serverConfig = this.serverService.getHTMLConfig() | ||
165 | |||
163 | this.updateForm() | 166 | this.updateForm() |
164 | 167 | ||
165 | this.pluginService.ensurePluginsAreLoaded('video-edit') | 168 | this.pluginService.ensurePluginsAreLoaded('video-edit') |
@@ -200,8 +203,6 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
200 | } | 203 | } |
201 | }) | 204 | }) |
202 | 205 | ||
203 | this.serverConfig = this.serverService.getHTMLConfig() | ||
204 | |||
205 | this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) | 206 | this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id) |
206 | 207 | ||
207 | this.ngZone.runOutsideAngular(() => { | 208 | this.ngZone.runOutsideAngular(() => { |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts index 01eabb0d7..46a7ebb0b 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts | |||
@@ -70,8 +70,6 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView | |||
70 | privacy: this.highestPrivacy, | 70 | privacy: this.highestPrivacy, |
71 | nsfw: this.serverConfig.instance.isNSFW, | 71 | nsfw: this.serverConfig.instance.isNSFW, |
72 | waitTranscoding: true, | 72 | waitTranscoding: true, |
73 | commentsEnabled: true, | ||
74 | downloadEnabled: true, | ||
75 | permanentLive: this.firstStepPermanentLive, | 73 | permanentLive: this.firstStepPermanentLive, |
76 | saveReplay: this.firstStepPermanentLive === false && this.isReplayAllowed(), | 74 | saveReplay: this.firstStepPermanentLive === false && this.isReplayAllowed(), |
77 | channelId: this.firstStepChannelId | 75 | channelId: this.firstStepChannelId |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts index 87e47683f..5e758910e 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts | |||
@@ -81,8 +81,6 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Af | |||
81 | const videoUpdate: VideoUpdate = { | 81 | const videoUpdate: VideoUpdate = { |
82 | privacy: this.highestPrivacy, | 82 | privacy: this.highestPrivacy, |
83 | waitTranscoding: false, | 83 | waitTranscoding: false, |
84 | commentsEnabled: true, | ||
85 | downloadEnabled: true, | ||
86 | channelId: this.firstStepChannelId | 84 | channelId: this.firstStepChannelId |
87 | } | 85 | } |
88 | 86 | ||
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts index 3487c1adf..2ea70ed55 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts | |||
@@ -68,8 +68,6 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, AfterV | |||
68 | const videoUpdate: VideoUpdate = { | 68 | const videoUpdate: VideoUpdate = { |
69 | privacy: this.highestPrivacy, | 69 | privacy: this.highestPrivacy, |
70 | waitTranscoding: false, | 70 | waitTranscoding: false, |
71 | commentsEnabled: true, | ||
72 | downloadEnabled: true, | ||
73 | channelId: this.firstStepChannelId | 71 | channelId: this.firstStepChannelId |
74 | } | 72 | } |
75 | 73 | ||
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts index efa8c85a3..5e086ef42 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts | |||
@@ -49,7 +49,9 @@ export abstract class VideoSend extends FormReactive implements OnInit { | |||
49 | this.serverService.getVideoPrivacies() | 49 | this.serverService.getVideoPrivacies() |
50 | .subscribe( | 50 | .subscribe( |
51 | privacies => { | 51 | privacies => { |
52 | const { videoPrivacies, defaultPrivacyId } = this.videoService.explainedPrivacyLabels(privacies) | 52 | const defaultPrivacy = this.serverConfig.defaults.publish.privacy |
53 | |||
54 | const { videoPrivacies, defaultPrivacyId } = this.videoService.explainedPrivacyLabels(privacies, defaultPrivacy) | ||
53 | 55 | ||
54 | this.videoPrivacies = videoPrivacies | 56 | this.videoPrivacies = videoPrivacies |
55 | this.firstStepPrivacyId = defaultPrivacyId | 57 | this.firstStepPrivacyId = defaultPrivacyId |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts index 28d7ec458..76f154249 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts | |||
@@ -277,8 +277,6 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
277 | private uploadFile (file: File, previewfile?: File) { | 277 | private uploadFile (file: File, previewfile?: File) { |
278 | const metadata = { | 278 | const metadata = { |
279 | waitTranscoding: true, | 279 | waitTranscoding: true, |
280 | commentsEnabled: true, | ||
281 | downloadEnabled: true, | ||
282 | channelId: this.firstStepChannelId, | 280 | channelId: this.firstStepChannelId, |
283 | nsfw: this.serverConfig.instance.isNSFW, | 281 | nsfw: this.serverConfig.instance.isNSFW, |
284 | privacy: this.highestPrivacy.toString(), | 282 | privacy: this.highestPrivacy.toString(), |
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html index 8fb244cc4..f23efca98 100644 --- a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | <ng-container *ngIf="!isUserLoggedIn && !video.isLive"> | 37 | <ng-container *ngIf="!isUserLoggedIn && !video.isLive"> |
38 | <button | 38 | <button |
39 | *ngIf="isVideoDownloadable()" class="action-button action-button-save" | 39 | *ngIf="isVideoDownloadable()" class="action-button action-button-download" |
40 | (click)="showDownloadModal()" (keydown.enter)="showDownloadModal()" | 40 | (click)="showDownloadModal()" (keydown.enter)="showDownloadModal()" |
41 | > | 41 | > |
42 | <my-global-icon iconName="download" aria-hidden="true"></my-global-icon> | 42 | <my-global-icon iconName="download" aria-hidden="true"></my-global-icon> |
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss index 967d515e6..fdf4e3edb 100644 --- a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss | |||
@@ -49,7 +49,8 @@ | |||
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | &.action-button-save { | 52 | &.action-button-save, |
53 | &.action-button-download { | ||
53 | my-global-icon { | 54 | my-global-icon { |
54 | top: 0 !important; | 55 | top: 0 !important; |
55 | right: -1px; | 56 | right: -1px; |
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-attributes.component.html b/client/src/app/+videos/+video-watch/shared/metadata/video-attributes.component.html index d65c9356a..10ff46595 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-attributes.component.html +++ b/client/src/app/+videos/+video-watch/shared/metadata/video-attributes.component.html | |||
@@ -1,9 +1,9 @@ | |||
1 | <div class="attribute"> | 1 | <div class="attribute attribute-privacy"> |
2 | <span i18n class="attribute-label">Privacy</span> | 2 | <span i18n class="attribute-label">Privacy</span> |
3 | <span class="attribute-value">{{ video.privacy.label }}</span> | 3 | <span class="attribute-value">{{ video.privacy.label }}</span> |
4 | </div> | 4 | </div> |
5 | 5 | ||
6 | <div *ngIf="video.isLocal === false" class="attribute"> | 6 | <div *ngIf="video.isLocal === false" class="attribute attribute-origin"> |
7 | <span i18n class="attribute-label">Origin</span> | 7 | <span i18n class="attribute-label">Origin</span> |
8 | <a | 8 | <a |
9 | class="attribute-value" target="_blank" rel="noopener noreferrer" | 9 | class="attribute-value" target="_blank" rel="noopener noreferrer" |
@@ -16,12 +16,12 @@ | |||
16 | ></a> | 16 | ></a> |
17 | </div> | 17 | </div> |
18 | 18 | ||
19 | <div *ngIf="!!video.originallyPublishedAt" class="attribute"> | 19 | <div *ngIf="!!video.originallyPublishedAt" class="attribute attribute-originally-published-at"> |
20 | <span i18n class="attribute-label">Originally published</span> | 20 | <span i18n class="attribute-label">Originally published</span> |
21 | <span class="attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span> | 21 | <span class="attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span> |
22 | </div> | 22 | </div> |
23 | 23 | ||
24 | <div class="attribute"> | 24 | <div class="attribute attribute-category"> |
25 | <span i18n class="attribute-label">Category</span> | 25 | <span i18n class="attribute-label">Category</span> |
26 | <span *ngIf="!video.category.id" class="attribute-value">{{ video.category.label }}</span> | 26 | <span *ngIf="!video.category.id" class="attribute-value">{{ video.category.label }}</span> |
27 | <a | 27 | <a |
@@ -30,7 +30,7 @@ | |||
30 | >{{ video.category.label }}</a> | 30 | >{{ video.category.label }}</a> |
31 | </div> | 31 | </div> |
32 | 32 | ||
33 | <div class="attribute"> | 33 | <div class="attribute attribute-licence"> |
34 | <span i18n class="attribute-label">Licence</span> | 34 | <span i18n class="attribute-label">Licence</span> |
35 | <span *ngIf="!video.licence.id" class="attribute-value">{{ video.licence.label }}</span> | 35 | <span *ngIf="!video.licence.id" class="attribute-value">{{ video.licence.label }}</span> |
36 | <a | 36 | <a |
@@ -39,7 +39,7 @@ | |||
39 | >{{ video.licence.label }}</a> | 39 | >{{ video.licence.label }}</a> |
40 | </div> | 40 | </div> |
41 | 41 | ||
42 | <div class="attribute"> | 42 | <div class="attribute attribute-language"> |
43 | <span i18n class="attribute-label">Language</span> | 43 | <span i18n class="attribute-label">Language</span> |
44 | <span *ngIf="!video.language.id" class="attribute-value">{{ video.language.label }}</span> | 44 | <span *ngIf="!video.language.id" class="attribute-value">{{ video.language.label }}</span> |
45 | <a | 45 | <a |
@@ -56,7 +56,7 @@ | |||
56 | >{{ tag }}</a> | 56 | >{{ tag }}</a> |
57 | </div> | 57 | </div> |
58 | 58 | ||
59 | <div class="attribute" *ngIf="!video.isLive"> | 59 | <div class="attribute attribute-duration" *ngIf="!video.isLive"> |
60 | <span i18n class="attribute-label">Duration</span> | 60 | <span i18n class="attribute-label">Duration</span> |
61 | <span class="attribute-value">{{ video.duration | myDurationFormatter }}</span> | 61 | <span class="attribute-value">{{ video.duration | myDurationFormatter }}</span> |
62 | </div> | 62 | </div> |
diff --git a/config/default.yaml b/config/default.yaml index 074951117..fbe0dbbfb 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -75,18 +75,22 @@ email: | |||
75 | subject: | 75 | subject: |
76 | prefix: '[PeerTube]' | 76 | prefix: '[PeerTube]' |
77 | 77 | ||
78 | # PeerTube client/interface configuration | 78 | # Update default PeerTube values |
79 | client: | 79 | # Set by API when the field is not provided and put as default value in client |
80 | videos: | 80 | defaults: |
81 | miniature: | 81 | # Change default values when publishing a video (upload/import/go Live) |
82 | # By default PeerTube client displays author username | 82 | publish: |
83 | prefer_author_display_name: false | 83 | download_enabled: true |
84 | 84 | ||
85 | menu: | 85 | comments_enabled: true |
86 | login: | 86 | |
87 | # If you enable only one external auth plugin | 87 | # public = 1, unlisted = 2, private = 3, internal = 4 |
88 | # You can automatically redirect your users on this external platform when they click on the login button | 88 | privacy: 1 |
89 | redirect_on_single_external_auth: false | 89 | |
90 | # CC-BY = 1, CC-SA = 2, CC-ND = 3, CC-NC = 4, CC-NC-SA = 5, CC-NC-ND = 6, Public Domain = 7 | ||
91 | # You can also choose a custom licence value added by a plugin | ||
92 | # No licence by default | ||
93 | licence: null | ||
90 | 94 | ||
91 | # From the project root directory | 95 | # From the project root directory |
92 | storage: | 96 | storage: |
@@ -587,3 +591,16 @@ search: | |||
587 | disable_local_search: false | 591 | disable_local_search: false |
588 | # If you did not disable local search, you can decide to use the search index by default | 592 | # If you did not disable local search, you can decide to use the search index by default |
589 | is_default_search: false | 593 | is_default_search: false |
594 | |||
595 | # PeerTube client/interface configuration | ||
596 | client: | ||
597 | videos: | ||
598 | miniature: | ||
599 | # By default PeerTube client displays author username | ||
600 | prefer_author_display_name: false | ||
601 | |||
602 | menu: | ||
603 | login: | ||
604 | # If you enable only one external auth plugin | ||
605 | # You can automatically redirect your users on this external platform when they click on the login button | ||
606 | redirect_on_single_external_auth: false | ||
diff --git a/config/production.yaml.example b/config/production.yaml.example index e38b79587..6363a5179 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example | |||
@@ -73,18 +73,22 @@ email: | |||
73 | subject: | 73 | subject: |
74 | prefix: '[PeerTube]' | 74 | prefix: '[PeerTube]' |
75 | 75 | ||
76 | # PeerTube client/interface configuration | 76 | # Update default PeerTube values |
77 | client: | 77 | # Set by API when the field is not provided and put as default value in client |
78 | videos: | 78 | defaults: |
79 | miniature: | 79 | # Change default values when publishing a video (upload/import/go Live) |
80 | # By default PeerTube client displays author username | 80 | publish: |
81 | prefer_author_display_name: false | 81 | download_enabled: true |
82 | 82 | ||
83 | menu: | 83 | comments_enabled: true |
84 | login: | 84 | |
85 | # If you enable only one external auth plugin | 85 | # public = 1, unlisted = 2, private = 3, internal = 4 |
86 | # You can automatically redirect your users on this external platform when they click on the login button | 86 | privacy: 1 |
87 | redirect_on_single_external_auth: false | 87 | |
88 | # CC-BY = 1, CC-SA = 2, CC-ND = 3, CC-NC = 4, CC-NC-SA = 5, CC-NC-ND = 6, Public Domain = 7 | ||
89 | # You can also choose a custom licence value added by a plugin | ||
90 | # No licence by default | ||
91 | licence: null | ||
88 | 92 | ||
89 | # From the project root directory | 93 | # From the project root directory |
90 | storage: | 94 | storage: |
@@ -597,3 +601,16 @@ search: | |||
597 | disable_local_search: false | 601 | disable_local_search: false |
598 | # If you did not disable local search, you can decide to use the search index by default | 602 | # If you did not disable local search, you can decide to use the search index by default |
599 | is_default_search: false | 603 | is_default_search: false |
604 | |||
605 | # PeerTube client/interface configuration | ||
606 | client: | ||
607 | videos: | ||
608 | miniature: | ||
609 | # By default PeerTube client displays author username | ||
610 | prefer_author_display_name: false | ||
611 | |||
612 | menu: | ||
613 | login: | ||
614 | # If you enable only one external auth plugin | ||
615 | # You can automatically redirect your users on this external platform when they click on the login button | ||
616 | redirect_on_single_external_auth: false | ||
diff --git a/scripts/e2e/browserstack.sh b/scripts/e2e/browserstack.sh index fb125ea23..ad6268d42 100755 --- a/scripts/e2e/browserstack.sh +++ b/scripts/e2e/browserstack.sh | |||
@@ -2,8 +2,4 @@ | |||
2 | 2 | ||
3 | set -eu | 3 | set -eu |
4 | 4 | ||
5 | npm run clean:server:test | 5 | cd client/e2e && ../node_modules/.bin/wdio run ./wdio.browserstack.conf.ts |
6 | |||
7 | npm run concurrently -- -k -s first \ | ||
8 | "cd client/e2e && ../node_modules/.bin/wdio run ./wdio.browserstack.conf.ts" \ | ||
9 | "NODE_ENV=test NODE_APP_INSTANCE=1 NODE_CONFIG='{ \"rates_limit\": { \"api\": { \"max\": 5000 }, \"login\": { \"max\": 5000 } }, \"log\": { \"level\": \"warn\" }, \"signup\": { \"enabled\": false } }' node dist/server" | ||
diff --git a/scripts/e2e/local.sh b/scripts/e2e/local.sh index fe8b7f559..0e0368c52 100755 --- a/scripts/e2e/local.sh +++ b/scripts/e2e/local.sh | |||
@@ -2,16 +2,6 @@ | |||
2 | 2 | ||
3 | set -eu | 3 | set -eu |
4 | 4 | ||
5 | npm run clean:server:test | 5 | cd client/e2e |
6 | 6 | ||
7 | config="{" | 7 | ../node_modules/.bin/wdio run ./wdio.local.conf.ts |
8 | config+=" \"rates_limit\": { \"api\": { \"max\": 5000 }, \"login\": { \"max\": 5000 } }" | ||
9 | config+=", \"log\": { \"level\": \"warn\" }" | ||
10 | config+=", \"signup\": { \"enabled\": false }" | ||
11 | config+=", \"transcoding\": { \"enabled\": false }" | ||
12 | config+="}" | ||
13 | |||
14 | npm run concurrently -- -k -s first \ | ||
15 | "cd client/e2e && ../node_modules/.bin/wdio run ./wdio.local.conf.ts" \ | ||
16 | "NODE_ENV=test NODE_CONFIG='$config' NODE_APP_INSTANCE=1 node dist/server" \ | ||
17 | "NODE_ENV=test NODE_CONFIG='$config' NODE_APP_INSTANCE=2 node dist/server" | ||
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts index 52864bdfd..3c445efce 100644 --- a/server/controllers/api/videos/import.ts +++ b/server/controllers/api/videos/import.ts | |||
@@ -216,10 +216,10 @@ async function buildVideo (channelId: number, body: VideoImportCreate, importDat | |||
216 | name: body.name || importData.name || 'Unknown name', | 216 | name: body.name || importData.name || 'Unknown name', |
217 | remote: false, | 217 | remote: false, |
218 | category: body.category || importData.category, | 218 | category: body.category || importData.category, |
219 | licence: body.licence || importData.licence, | 219 | licence: body.licence ?? importData.licence ?? CONFIG.DEFAULTS.PUBLISH.LICENCE, |
220 | language: body.language || importData.language, | 220 | language: body.language || importData.language, |
221 | commentsEnabled: body.commentsEnabled !== false, // If the value is not "false", the default is "true" | 221 | commentsEnabled: body.commentsEnabled ?? CONFIG.DEFAULTS.PUBLISH.COMMENTS_ENABLED, |
222 | downloadEnabled: body.downloadEnabled !== false, | 222 | downloadEnabled: body.downloadEnabled ?? CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED, |
223 | waitTranscoding: body.waitTranscoding || false, | 223 | waitTranscoding: body.waitTranscoding || false, |
224 | state: VideoState.TO_IMPORT, | 224 | state: VideoState.TO_IMPORT, |
225 | nsfw: body.nsfw || importData.nsfw || false, | 225 | nsfw: body.nsfw || importData.nsfw || false, |
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index c85c389cd..2c24e20c8 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts | |||
@@ -34,6 +34,7 @@ function checkMissedConfig () { | |||
34 | 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'auto_blacklist.videos.of_users.enabled', | 34 | 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'auto_blacklist.videos.of_users.enabled', |
35 | 'trending.videos.interval_days', | 35 | 'trending.videos.interval_days', |
36 | 'client.videos.miniature.prefer_author_display_name', 'client.menu.login.redirect_on_single_external_auth', | 36 | 'client.videos.miniature.prefer_author_display_name', 'client.menu.login.redirect_on_single_external_auth', |
37 | 'defaults.publish.download_enabled', 'defaults.publish.comments_enabled', 'defaults.publish.privacy', 'defaults.publish.licence', | ||
37 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', | 38 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', |
38 | 'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt', | 39 | 'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt', |
39 | 'services.twitter.username', 'services.twitter.whitelisted', | 40 | 'services.twitter.username', 'services.twitter.whitelisted', |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index eb848be6b..70179d25c 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -4,7 +4,7 @@ import { dirname, join } from 'path' | |||
4 | import { decacheModule } from '@server/helpers/decache' | 4 | import { decacheModule } from '@server/helpers/decache' |
5 | import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' | 5 | import { VideoRedundancyConfigFilter } from '@shared/models/redundancy/video-redundancy-config-filter.type' |
6 | import { BroadcastMessageLevel } from '@shared/models/server' | 6 | import { BroadcastMessageLevel } from '@shared/models/server' |
7 | import { VideosRedundancyStrategy } from '../../shared/models' | 7 | import { VideoPrivacy, VideosRedundancyStrategy } from '../../shared/models' |
8 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' | 8 | import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type' |
9 | import { buildPath, parseBytes, parseDurationToMs, root } from '../helpers/core-utils' | 9 | import { buildPath, parseBytes, parseDurationToMs, root } from '../helpers/core-utils' |
10 | 10 | ||
@@ -71,6 +71,15 @@ const CONFIG = { | |||
71 | } | 71 | } |
72 | }, | 72 | }, |
73 | 73 | ||
74 | DEFAULTS: { | ||
75 | PUBLISH: { | ||
76 | DOWNLOAD_ENABLED: config.get<boolean>('defaults.publish.download_enabled'), | ||
77 | COMMENTS_ENABLED: config.get<boolean>('defaults.publish.comments_enabled'), | ||
78 | PRIVACY: config.get<VideoPrivacy>('defaults.publish.privacy'), | ||
79 | LICENCE: config.get<number>('defaults.publish.licence') | ||
80 | } | ||
81 | }, | ||
82 | |||
74 | STORAGE: { | 83 | STORAGE: { |
75 | TMP_DIR: buildPath(config.get<string>('storage.tmp')), | 84 | TMP_DIR: buildPath(config.get<string>('storage.tmp')), |
76 | BIN_DIR: buildPath(config.get<string>('storage.bin')), | 85 | BIN_DIR: buildPath(config.get<string>('storage.bin')), |
diff --git a/server/lib/server-config-manager.ts b/server/lib/server-config-manager.ts index 6aa459f82..8aea4cd6d 100644 --- a/server/lib/server-config-manager.ts +++ b/server/lib/server-config-manager.ts | |||
@@ -55,6 +55,15 @@ class ServerConfigManager { | |||
55 | } | 55 | } |
56 | }, | 56 | }, |
57 | 57 | ||
58 | defaults: { | ||
59 | publish: { | ||
60 | downloadEnabled: CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED, | ||
61 | commentsEnabled: CONFIG.DEFAULTS.PUBLISH.COMMENTS_ENABLED, | ||
62 | privacy: CONFIG.DEFAULTS.PUBLISH.PRIVACY, | ||
63 | licence: CONFIG.DEFAULTS.PUBLISH.LICENCE | ||
64 | } | ||
65 | }, | ||
66 | |||
58 | webadmin: { | 67 | webadmin: { |
59 | configuration: { | 68 | configuration: { |
60 | edition: { | 69 | edition: { |
diff --git a/server/lib/video.ts b/server/lib/video.ts index 1cfe4f27c..e5af028ea 100644 --- a/server/lib/video.ts +++ b/server/lib/video.ts | |||
@@ -9,16 +9,17 @@ import { MThumbnail, MUserId, MVideoFile, MVideoTag, MVideoThumbnail, MVideoUUID | |||
9 | import { ThumbnailType, VideoCreate, VideoPrivacy, VideoTranscodingPayload } from '@shared/models' | 9 | import { ThumbnailType, VideoCreate, VideoPrivacy, VideoTranscodingPayload } from '@shared/models' |
10 | import { CreateJobOptions, JobQueue } from './job-queue/job-queue' | 10 | import { CreateJobOptions, JobQueue } from './job-queue/job-queue' |
11 | import { updateVideoMiniatureFromExisting } from './thumbnail' | 11 | import { updateVideoMiniatureFromExisting } from './thumbnail' |
12 | import { CONFIG } from '@server/initializers/config' | ||
12 | 13 | ||
13 | function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> { | 14 | function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): FilteredModelAttributes<VideoModel> { |
14 | return { | 15 | return { |
15 | name: videoInfo.name, | 16 | name: videoInfo.name, |
16 | remote: false, | 17 | remote: false, |
17 | category: videoInfo.category, | 18 | category: videoInfo.category, |
18 | licence: videoInfo.licence, | 19 | licence: videoInfo.licence ?? CONFIG.DEFAULTS.PUBLISH.LICENCE, |
19 | language: videoInfo.language, | 20 | language: videoInfo.language, |
20 | commentsEnabled: videoInfo.commentsEnabled !== false, // If the value is not "false", the default is "true" | 21 | commentsEnabled: videoInfo.commentsEnabled ?? CONFIG.DEFAULTS.PUBLISH.COMMENTS_ENABLED, |
21 | downloadEnabled: videoInfo.downloadEnabled !== false, | 22 | downloadEnabled: videoInfo.downloadEnabled ?? CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED, |
22 | waitTranscoding: videoInfo.waitTranscoding || false, | 23 | waitTranscoding: videoInfo.waitTranscoding || false, |
23 | nsfw: videoInfo.nsfw || false, | 24 | nsfw: videoInfo.nsfw || false, |
24 | description: videoInfo.description, | 25 | description: videoInfo.description, |
diff --git a/server/tests/api/server/config-defaults.ts b/server/tests/api/server/config-defaults.ts new file mode 100644 index 000000000..2433d3119 --- /dev/null +++ b/server/tests/api/server/config-defaults.ts | |||
@@ -0,0 +1,116 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { cleanupTests, createSingleServer, FIXTURE_URLS, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/extra-utils' | ||
6 | import { VideoDetails, VideoPrivacy } from '@shared/models' | ||
7 | |||
8 | const expect = chai.expect | ||
9 | |||
10 | describe('Test config defaults', function () { | ||
11 | let server: PeerTubeServer | ||
12 | let channelId: number | ||
13 | |||
14 | before(async function () { | ||
15 | this.timeout(30000) | ||
16 | |||
17 | const overrideConfig = { | ||
18 | defaults: { | ||
19 | publish: { | ||
20 | comments_enabled: false, | ||
21 | download_enabled: false, | ||
22 | privacy: VideoPrivacy.INTERNAL, | ||
23 | licence: 4 | ||
24 | } | ||
25 | } | ||
26 | } | ||
27 | |||
28 | server = await createSingleServer(1, overrideConfig) | ||
29 | await setAccessTokensToServers([ server ]) | ||
30 | await setDefaultVideoChannel([ server ]) | ||
31 | |||
32 | channelId = server.store.channel.id | ||
33 | }) | ||
34 | |||
35 | describe('Default publish values', function () { | ||
36 | const attributes = { | ||
37 | name: 'video', | ||
38 | downloadEnabled: undefined, | ||
39 | commentsEnabled: undefined, | ||
40 | licence: undefined, | ||
41 | privacy: VideoPrivacy.PUBLIC // Privacy is mandatory for server | ||
42 | } | ||
43 | |||
44 | function checkVideo (video: VideoDetails) { | ||
45 | expect(video.downloadEnabled).to.be.false | ||
46 | expect(video.commentsEnabled).to.be.false | ||
47 | expect(video.licence.id).to.equal(4) | ||
48 | } | ||
49 | |||
50 | before(async function () { | ||
51 | await server.config.disableTranscoding() | ||
52 | await server.config.enableImports() | ||
53 | await server.config.enableLive({ allowReplay: false, transcoding: false }) | ||
54 | }) | ||
55 | |||
56 | it('Should have the correct server configuration', async function () { | ||
57 | const config = await server.config.getConfig() | ||
58 | |||
59 | expect(config.defaults.publish.commentsEnabled).to.be.false | ||
60 | expect(config.defaults.publish.downloadEnabled).to.be.false | ||
61 | expect(config.defaults.publish.licence).to.equal(4) | ||
62 | expect(config.defaults.publish.privacy).to.equal(VideoPrivacy.INTERNAL) | ||
63 | }) | ||
64 | |||
65 | it('Should respect default values when uploading a video', async function () { | ||
66 | for (const mode of [ 'legacy' as 'legacy', 'resumable' as 'resumable' ]) { | ||
67 | const { id } = await server.videos.upload({ attributes, mode }) | ||
68 | |||
69 | const video = await server.videos.get({ id }) | ||
70 | checkVideo(video) | ||
71 | } | ||
72 | }) | ||
73 | |||
74 | it('Should respect default values when importing a video using URL', async function () { | ||
75 | const { video: { id } } = await server.imports.importVideo({ | ||
76 | attributes: { | ||
77 | ...attributes, | ||
78 | channelId, | ||
79 | targetUrl: FIXTURE_URLS.goodVideo | ||
80 | } | ||
81 | }) | ||
82 | |||
83 | const video = await server.videos.get({ id }) | ||
84 | checkVideo(video) | ||
85 | }) | ||
86 | |||
87 | it('Should respect default values when importing a video using magnet URI', async function () { | ||
88 | const { video: { id } } = await server.imports.importVideo({ | ||
89 | attributes: { | ||
90 | ...attributes, | ||
91 | channelId, | ||
92 | magnetUri: FIXTURE_URLS.magnet | ||
93 | } | ||
94 | }) | ||
95 | |||
96 | const video = await server.videos.get({ id }) | ||
97 | checkVideo(video) | ||
98 | }) | ||
99 | |||
100 | it('Should respect default values when creating a live', async function () { | ||
101 | const { id } = await server.live.create({ | ||
102 | fields: { | ||
103 | ...attributes, | ||
104 | channelId | ||
105 | } | ||
106 | }) | ||
107 | |||
108 | const video = await server.videos.get({ id }) | ||
109 | checkVideo(video) | ||
110 | }) | ||
111 | }) | ||
112 | |||
113 | after(async function () { | ||
114 | await cleanupTests([ server ]) | ||
115 | }) | ||
116 | }) | ||
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts index 8136fc3c6..45be107ce 100644 --- a/server/tests/api/server/index.ts +++ b/server/tests/api/server/index.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import './auto-follows' | 1 | import './auto-follows' |
2 | import './bulk' | ||
3 | import './config-defaults' | ||
2 | import './config' | 4 | import './config' |
3 | import './contact-form' | 5 | import './contact-form' |
4 | import './email' | 6 | import './email' |
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index 9f17276e0..9c3dcd6d3 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { VideoPrivacy } from '../videos/video-privacy.enum' | ||
1 | import { ClientScript } from '../plugins/plugin-package-json.model' | 2 | import { ClientScript } from '../plugins/plugin-package-json.model' |
2 | import { NSFWPolicyType } from '../videos/nsfw-policy.type' | 3 | import { NSFWPolicyType } from '../videos/nsfw-policy.type' |
3 | import { BroadcastMessageLevel } from './broadcast-message-level.type' | 4 | import { BroadcastMessageLevel } from './broadcast-message-level.type' |
@@ -47,6 +48,15 @@ export interface ServerConfig { | |||
47 | } | 48 | } |
48 | } | 49 | } |
49 | 50 | ||
51 | defaults: { | ||
52 | publish: { | ||
53 | downloadEnabled: boolean | ||
54 | commentsEnabled: boolean | ||
55 | privacy: VideoPrivacy | ||
56 | licence: number | ||
57 | } | ||
58 | } | ||
59 | |||
50 | webadmin: { | 60 | webadmin: { |
51 | configuration: { | 61 | configuration: { |
52 | edition: { | 62 | edition: { |
diff --git a/support/doc/development/tests.md b/support/doc/development/tests.md index d36cf8544..02fc41147 100644 --- a/support/doc/development/tests.md +++ b/support/doc/development/tests.md | |||
@@ -88,13 +88,7 @@ $ BROWSERSTACK_USER=your_user BROWSERSTACK_KEY=your_key npm run e2e:browserstack | |||
88 | 88 | ||
89 | ### Add E2E tests | 89 | ### Add E2E tests |
90 | 90 | ||
91 | To add E2E tests and quickly run tests using a local Chrome, first create a test instance: | 91 | To add E2E tests and quickly run tests using a local Chrome: |
92 | |||
93 | ```bash | ||
94 | $ npm run clean:server:test && NODE_APP_INSTANCE=1 NODE_ENV=test npm start | ||
95 | ``` | ||
96 | |||
97 | Then, just run your suite using: | ||
98 | 92 | ||
99 | ```bash | 93 | ```bash |
100 | $ cd client/e2e | 94 | $ cd client/e2e |