aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests')
-rw-r--r--server/tests/api/check-params/config.ts3
-rw-r--r--server/tests/api/check-params/custom-pages.ts81
-rw-r--r--server/tests/api/check-params/index.ts1
-rw-r--r--server/tests/api/check-params/plugins.ts12
-rw-r--r--server/tests/api/moderation/blocklist.ts56
-rw-r--r--server/tests/api/notifications/comments-notifications.ts25
-rw-r--r--server/tests/api/server/bulk.ts9
-rw-r--r--server/tests/api/server/config.ts5
-rw-r--r--server/tests/api/server/follows.ts48
-rw-r--r--server/tests/api/server/handle-down.ts12
-rw-r--r--server/tests/api/server/homepage.ts85
-rw-r--r--server/tests/api/server/index.ts1
-rw-r--r--server/tests/api/server/plugins.ts10
-rw-r--r--server/tests/api/server/services.ts104
-rw-r--r--server/tests/api/videos/multiple-servers.ts13
-rw-r--r--server/tests/api/videos/video-comments.ts3
-rw-r--r--server/tests/client.ts396
-rw-r--r--server/tests/plugins/filter-hooks.ts2
18 files changed, 568 insertions, 298 deletions
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 004aa65b3..9549070ef 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -73,7 +73,8 @@ describe('Test config API validators', function () {
73 signup: { 73 signup: {
74 enabled: false, 74 enabled: false,
75 limit: 5, 75 limit: 5,
76 requiresEmailVerification: false 76 requiresEmailVerification: false,
77 minimumAge: 16
77 }, 78 },
78 admin: { 79 admin: {
79 email: 'superadmin1@example.com' 80 email: 'superadmin1@example.com'
diff --git a/server/tests/api/check-params/custom-pages.ts b/server/tests/api/check-params/custom-pages.ts
new file mode 100644
index 000000000..74ca3384c
--- /dev/null
+++ b/server/tests/api/check-params/custom-pages.ts
@@ -0,0 +1,81 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
5import {
6 cleanupTests,
7 createUser,
8 flushAndRunServer,
9 ServerInfo,
10 setAccessTokensToServers,
11 userLogin
12} from '../../../../shared/extra-utils'
13import { makeGetRequest, makePutBodyRequest } from '../../../../shared/extra-utils/requests/requests'
14
15describe('Test custom pages validators', function () {
16 const path = '/api/v1/custom-pages/homepage/instance'
17
18 let server: ServerInfo
19 let userAccessToken: string
20
21 // ---------------------------------------------------------------
22
23 before(async function () {
24 this.timeout(120000)
25
26 server = await flushAndRunServer(1)
27 await setAccessTokensToServers([ server ])
28
29 const user = { username: 'user1', password: 'password' }
30 await createUser({ url: server.url, accessToken: server.accessToken, username: user.username, password: user.password })
31
32 userAccessToken = await userLogin(server, user)
33 })
34
35 describe('When updating instance homepage', function () {
36
37 it('Should fail with an unauthenticated user', async function () {
38 await makePutBodyRequest({
39 url: server.url,
40 path,
41 fields: { content: 'super content' },
42 statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401
43 })
44 })
45
46 it('Should fail with a non admin user', async function () {
47 await makePutBodyRequest({
48 url: server.url,
49 path,
50 token: userAccessToken,
51 fields: { content: 'super content' },
52 statusCodeExpected: HttpStatusCode.FORBIDDEN_403
53 })
54 })
55
56 it('Should succeed with the correct params', async function () {
57 await makePutBodyRequest({
58 url: server.url,
59 path,
60 token: server.accessToken,
61 fields: { content: 'super content' },
62 statusCodeExpected: HttpStatusCode.NO_CONTENT_204
63 })
64 })
65 })
66
67 describe('When getting instance homapage', function () {
68
69 it('Should succeed with the correct params', async function () {
70 await makeGetRequest({
71 url: server.url,
72 path,
73 statusCodeExpected: HttpStatusCode.OK_200
74 })
75 })
76 })
77
78 after(async function () {
79 await cleanupTests([ server ])
80 })
81})
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts
index 143515838..ce2335e42 100644
--- a/server/tests/api/check-params/index.ts
+++ b/server/tests/api/check-params/index.ts
@@ -3,6 +3,7 @@ import './accounts'
3import './blocklist' 3import './blocklist'
4import './bulk' 4import './bulk'
5import './config' 5import './config'
6import './custom-pages'
6import './contact-form' 7import './contact-form'
7import './debug' 8import './debug'
8import './follows' 9import './follows'
diff --git a/server/tests/api/check-params/plugins.ts b/server/tests/api/check-params/plugins.ts
index 6e540bcbb..a833fe6ff 100644
--- a/server/tests/api/check-params/plugins.ts
+++ b/server/tests/api/check-params/plugins.ts
@@ -1,7 +1,7 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import 'mocha' 3import 'mocha'
4 4import { HttpStatusCode } from '@shared/core-utils'
5import { 5import {
6 checkBadCountPagination, 6 checkBadCountPagination,
7 checkBadSortPagination, 7 checkBadSortPagination,
@@ -11,14 +11,14 @@ import {
11 flushAndRunServer, 11 flushAndRunServer,
12 immutableAssign, 12 immutableAssign,
13 installPlugin, 13 installPlugin,
14 makeGetRequest, makePostBodyRequest, makePutBodyRequest, 14 makeGetRequest,
15 makePostBodyRequest,
16 makePutBodyRequest,
15 ServerInfo, 17 ServerInfo,
16 setAccessTokensToServers, 18 setAccessTokensToServers,
17 userLogin 19 userLogin
18} from '../../../../shared/extra-utils' 20} from '@shared/extra-utils'
19import { PluginType } from '../../../../shared/models/plugins/plugin.type' 21import { PeerTubePlugin, PluginType } from '@shared/models'
20import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugin.model'
21import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
22 22
23describe('Test server plugins API validators', function () { 23describe('Test server plugins API validators', function () {
24 let server: ServerInfo 24 let server: ServerInfo
diff --git a/server/tests/api/moderation/blocklist.ts b/server/tests/api/moderation/blocklist.ts
index e8202aff1..b767d38c7 100644
--- a/server/tests/api/moderation/blocklist.ts
+++ b/server/tests/api/moderation/blocklist.ts
@@ -1,46 +1,50 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
5import { AccountBlock, ServerBlock, Video, UserNotification, UserNotificationType } from '../../../../shared/index' 4import * as chai from 'chai'
6import { 5import {
6 addAccountToAccountBlocklist,
7 addAccountToServerBlocklist,
8 addServerToAccountBlocklist,
9 addServerToServerBlocklist,
10 addVideoCommentReply,
11 addVideoCommentThread,
7 cleanupTests, 12 cleanupTests,
8 createUser, 13 createUser,
9 deleteVideoComment, 14 deleteVideoComment,
10 doubleFollow, 15 doubleFollow,
16 findCommentId,
11 flushAndRunMultipleServers, 17 flushAndRunMultipleServers,
12 ServerInfo,
13 uploadVideo,
14 userLogin,
15 follow, 18 follow,
16 unfollow
17} from '../../../../shared/extra-utils/index'
18import { setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
19import { getVideosList, getVideosListWithToken } from '../../../../shared/extra-utils/videos/videos'
20import {
21 addVideoCommentReply,
22 addVideoCommentThread,
23 getVideoCommentThreads,
24 getVideoThreadComments,
25 findCommentId
26} from '../../../../shared/extra-utils/videos/video-comments'
27import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
28import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
29import {
30 addAccountToAccountBlocklist,
31 addAccountToServerBlocklist,
32 addServerToAccountBlocklist,
33 addServerToServerBlocklist,
34 getAccountBlocklistByAccount, 19 getAccountBlocklistByAccount,
35 getAccountBlocklistByServer, 20 getAccountBlocklistByServer,
36 getServerBlocklistByAccount, 21 getServerBlocklistByAccount,
37 getServerBlocklistByServer, 22 getServerBlocklistByServer,
23 getUserNotifications,
24 getVideoCommentThreads,
25 getVideosList,
26 getVideosListWithToken,
27 getVideoThreadComments,
38 removeAccountFromAccountBlocklist, 28 removeAccountFromAccountBlocklist,
39 removeAccountFromServerBlocklist, 29 removeAccountFromServerBlocklist,
40 removeServerFromAccountBlocklist, 30 removeServerFromAccountBlocklist,
41 removeServerFromServerBlocklist 31 removeServerFromServerBlocklist,
42} from '../../../../shared/extra-utils/users/blocklist' 32 ServerInfo,
43import { getUserNotifications } from '../../../../shared/extra-utils/users/user-notifications' 33 setAccessTokensToServers,
34 unfollow,
35 uploadVideo,
36 userLogin,
37 waitJobs
38} from '@shared/extra-utils'
39import {
40 AccountBlock,
41 ServerBlock,
42 UserNotification,
43 UserNotificationType,
44 Video,
45 VideoComment,
46 VideoCommentThreadTree
47} from '@shared/models'
44 48
45const expect = chai.expect 49const expect = chai.expect
46 50
diff --git a/server/tests/api/notifications/comments-notifications.ts b/server/tests/api/notifications/comments-notifications.ts
index 5e4ab0d6c..d2badf237 100644
--- a/server/tests/api/notifications/comments-notifications.ts
+++ b/server/tests/api/notifications/comments-notifications.ts
@@ -2,20 +2,25 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { cleanupTests, getVideoCommentThreads, getVideoThreadComments, updateMyUser } from '../../../../shared/extra-utils'
6import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index'
7import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
8import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
9import { addAccountToAccountBlocklist, removeAccountFromAccountBlocklist } from '../../../../shared/extra-utils/users/blocklist'
10import { 5import {
6 addAccountToAccountBlocklist,
7 addVideoCommentReply,
8 addVideoCommentThread,
11 checkCommentMention, 9 checkCommentMention,
12 CheckerBaseParams, 10 CheckerBaseParams,
13 checkNewCommentOnMyVideo, 11 checkNewCommentOnMyVideo,
14 prepareNotificationsTest 12 cleanupTests,
15} from '../../../../shared/extra-utils/users/user-notifications' 13 getVideoCommentThreads,
16import { addVideoCommentReply, addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' 14 getVideoThreadComments,
17import { UserNotification } from '../../../../shared/models/users' 15 MockSmtpServer,
18import { VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' 16 prepareNotificationsTest,
17 removeAccountFromAccountBlocklist,
18 ServerInfo,
19 updateMyUser,
20 uploadVideo,
21 waitJobs
22} from '@shared/extra-utils'
23import { UserNotification, VideoCommentThreadTree } from '@shared/models'
19 24
20const expect = chai.expect 25const expect = chai.expect
21 26
diff --git a/server/tests/api/server/bulk.ts b/server/tests/api/server/bulk.ts
index 51ba0e7af..80fa7fce6 100644
--- a/server/tests/api/server/bulk.ts
+++ b/server/tests/api/server/bulk.ts
@@ -2,12 +2,14 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { VideoComment } from '@shared/models/videos/video-comment.model' 5import { Video, VideoComment } from '@shared/models'
6import { 6import {
7 addVideoCommentReply,
7 addVideoCommentThread, 8 addVideoCommentThread,
8 bulkRemoveCommentsOf, 9 bulkRemoveCommentsOf,
9 cleanupTests, 10 cleanupTests,
10 createUser, 11 createUser,
12 doubleFollow,
11 flushAndRunMultipleServers, 13 flushAndRunMultipleServers,
12 getVideoCommentThreads, 14 getVideoCommentThreads,
13 getVideosList, 15 getVideosList,
@@ -15,11 +17,8 @@ import {
15 setAccessTokensToServers, 17 setAccessTokensToServers,
16 uploadVideo, 18 uploadVideo,
17 userLogin, 19 userLogin,
18 waitJobs, 20 waitJobs
19 addVideoCommentReply
20} from '../../../../shared/extra-utils/index' 21} from '../../../../shared/extra-utils/index'
21import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
22import { Video } from '@shared/models'
23 22
24const expect = chai.expect 23const expect = chai.expect
25 24
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index 1d9ea31df..19bf9582c 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -60,6 +60,7 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
60 60
61 expect(data.signup.enabled).to.be.true 61 expect(data.signup.enabled).to.be.true
62 expect(data.signup.limit).to.equal(4) 62 expect(data.signup.limit).to.equal(4)
63 expect(data.signup.minimumAge).to.equal(16)
63 expect(data.signup.requiresEmailVerification).to.be.false 64 expect(data.signup.requiresEmailVerification).to.be.false
64 65
65 expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com') 66 expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com')
@@ -151,6 +152,7 @@ function checkUpdatedConfig (data: CustomConfig) {
151 expect(data.signup.enabled).to.be.false 152 expect(data.signup.enabled).to.be.false
152 expect(data.signup.limit).to.equal(5) 153 expect(data.signup.limit).to.equal(5)
153 expect(data.signup.requiresEmailVerification).to.be.false 154 expect(data.signup.requiresEmailVerification).to.be.false
155 expect(data.signup.minimumAge).to.equal(10)
154 156
155 // We override admin email in parallel tests, so skip this exception 157 // We override admin email in parallel tests, so skip this exception
156 if (parallelTests() === false) { 158 if (parallelTests() === false) {
@@ -316,7 +318,8 @@ describe('Test config', function () {
316 signup: { 318 signup: {
317 enabled: false, 319 enabled: false,
318 limit: 5, 320 limit: 5,
319 requiresEmailVerification: false 321 requiresEmailVerification: false,
322 minimumAge: 10
320 }, 323 },
321 admin: { 324 admin: {
322 email: 'superadmin1@example.com' 325 email: 'superadmin1@example.com'
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts
index eb9ab10eb..e1c062020 100644
--- a/server/tests/api/server/follows.ts
+++ b/server/tests/api/server/follows.ts
@@ -1,37 +1,35 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
5import { Video, VideoPrivacy } from '../../../../shared/models/videos' 4import * as chai from 'chai'
6import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
7import { cleanupTests, completeVideoCheck, deleteVideoComment } from '../../../../shared/extra-utils'
8import { 5import {
6 addVideoCommentReply,
7 addVideoCommentThread,
8 cleanupTests,
9 completeVideoCheck,
10 createUser,
11 createVideoCaption,
12 dateIsValid,
13 deleteVideoComment,
14 expectAccountFollows,
9 flushAndRunMultipleServers, 15 flushAndRunMultipleServers,
10 getVideosList,
11 ServerInfo,
12 setAccessTokensToServers,
13 uploadVideo
14} from '../../../../shared/extra-utils/index'
15import { dateIsValid } from '../../../../shared/extra-utils/miscs/miscs'
16import {
17 follow, 16 follow,
18 getFollowersListPaginationAndSort, 17 getFollowersListPaginationAndSort,
19 getFollowingListPaginationAndSort, 18 getFollowingListPaginationAndSort,
20 unfollow
21} from '../../../../shared/extra-utils/server/follows'
22import { expectAccountFollows } from '../../../../shared/extra-utils/users/accounts'
23import { userLogin } from '../../../../shared/extra-utils/users/login'
24import { createUser } from '../../../../shared/extra-utils/users/users'
25import {
26 addVideoCommentReply,
27 addVideoCommentThread,
28 getVideoCommentThreads, 19 getVideoCommentThreads,
29 getVideoThreadComments 20 getVideosList,
30} from '../../../../shared/extra-utils/videos/video-comments' 21 getVideoThreadComments,
31import { rateVideo } from '../../../../shared/extra-utils/videos/videos' 22 listVideoCaptions,
32import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 23 rateVideo,
33import { createVideoCaption, listVideoCaptions, testCaptionFile } from '../../../../shared/extra-utils/videos/video-captions' 24 ServerInfo,
34import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' 25 setAccessTokensToServers,
26 testCaptionFile,
27 unfollow,
28 uploadVideo,
29 userLogin,
30 waitJobs
31} from '@shared/extra-utils'
32import { Video, VideoCaption, VideoComment, VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
35 33
36const expect = chai.expect 34const expect = chai.expect
37 35
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
index 817c79f6e..fe4a0e100 100644
--- a/server/tests/api/server/handle-down.ts
+++ b/server/tests/api/server/handle-down.ts
@@ -4,7 +4,7 @@ import * as chai from 'chai'
4import 'mocha' 4import 'mocha'
5import { JobState, Video } from '../../../../shared/models' 5import { JobState, Video } from '../../../../shared/models'
6import { VideoPrivacy } from '../../../../shared/models/videos' 6import { VideoPrivacy } from '../../../../shared/models/videos'
7import { VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' 7import { VideoCommentThreadTree } from '../../../../shared/models/videos/comment/video-comment.model'
8 8
9import { 9import {
10 cleanupTests, 10 cleanupTests,
@@ -346,10 +346,12 @@ describe('Test handle downs', function () {
346 // Wait video expiration 346 // Wait video expiration
347 await wait(11000) 347 await wait(11000)
348 348
349 for (let i = 0; i < 3; i++) { 349 for (let i = 0; i < 5; i++) {
350 await getVideo(servers[1].url, videoIdsServer1[i]) 350 try {
351 await waitJobs([ servers[1] ]) 351 await getVideo(servers[1].url, videoIdsServer1[i])
352 await wait(1500) 352 await waitJobs([ servers[1] ])
353 await wait(1500)
354 } catch {}
353 } 355 }
354 356
355 for (const id of videoIdsServer1) { 357 for (const id of videoIdsServer1) {
diff --git a/server/tests/api/server/homepage.ts b/server/tests/api/server/homepage.ts
new file mode 100644
index 000000000..e8ba89ca6
--- /dev/null
+++ b/server/tests/api/server/homepage.ts
@@ -0,0 +1,85 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import * as chai from 'chai'
5import { HttpStatusCode } from '@shared/core-utils'
6import { CustomPage, ServerConfig } from '@shared/models'
7import {
8 cleanupTests,
9 flushAndRunServer,
10 getConfig,
11 getInstanceHomepage,
12 killallServers,
13 reRunServer,
14 ServerInfo,
15 setAccessTokensToServers,
16 updateInstanceHomepage
17} from '../../../../shared/extra-utils/index'
18
19const expect = chai.expect
20
21async function getHomepageState (server: ServerInfo) {
22 const res = await getConfig(server.url)
23
24 const config = res.body as ServerConfig
25 return config.homepage.enabled
26}
27
28describe('Test instance homepage actions', function () {
29 let server: ServerInfo
30
31 before(async function () {
32 this.timeout(30000)
33
34 server = await flushAndRunServer(1)
35 await setAccessTokensToServers([ server ])
36 })
37
38 it('Should not have a homepage', async function () {
39 const state = await getHomepageState(server)
40 expect(state).to.be.false
41
42 await getInstanceHomepage(server.url, HttpStatusCode.NOT_FOUND_404)
43 })
44
45 it('Should set a homepage', async function () {
46 await updateInstanceHomepage(server.url, server.accessToken, '<picsou-magazine></picsou-magazine>')
47
48 const res = await getInstanceHomepage(server.url)
49 const page: CustomPage = res.body
50 expect(page.content).to.equal('<picsou-magazine></picsou-magazine>')
51
52 const state = await getHomepageState(server)
53 expect(state).to.be.true
54 })
55
56 it('Should have the same homepage after a restart', async function () {
57 this.timeout(30000)
58
59 killallServers([ server ])
60
61 await reRunServer(server)
62
63 const res = await getInstanceHomepage(server.url)
64 const page: CustomPage = res.body
65 expect(page.content).to.equal('<picsou-magazine></picsou-magazine>')
66
67 const state = await getHomepageState(server)
68 expect(state).to.be.true
69 })
70
71 it('Should empty the homepage', async function () {
72 await updateInstanceHomepage(server.url, server.accessToken, '')
73
74 const res = await getInstanceHomepage(server.url)
75 const page: CustomPage = res.body
76 expect(page.content).to.be.empty
77
78 const state = await getHomepageState(server)
79 expect(state).to.be.false
80 })
81
82 after(async function () {
83 await cleanupTests([ server ])
84 })
85})
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts
index be743973a..56e6eb5da 100644
--- a/server/tests/api/server/index.ts
+++ b/server/tests/api/server/index.ts
@@ -5,6 +5,7 @@ import './email'
5import './follow-constraints' 5import './follow-constraints'
6import './follows' 6import './follows'
7import './follows-moderation' 7import './follows-moderation'
8import './homepage'
8import './handle-down' 9import './handle-down'
9import './jobs' 10import './jobs'
10import './logs' 11import './logs'
diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts
index f4190c352..6046ab97e 100644
--- a/server/tests/api/server/plugins.ts
+++ b/server/tests/api/server/plugins.ts
@@ -28,14 +28,8 @@ import {
28 updatePluginSettings, 28 updatePluginSettings,
29 wait, 29 wait,
30 waitUntilLog 30 waitUntilLog
31} from '../../../../shared/extra-utils' 31} from '@shared/extra-utils'
32import { PeerTubePluginIndex } from '../../../../shared/models/plugins/peertube-plugin-index.model' 32import { PeerTubePlugin, PeerTubePluginIndex, PluginPackageJson, PluginType, PublicServerSetting, ServerConfig, User } from '@shared/models'
33import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugin.model'
34import { PluginPackageJson } from '../../../../shared/models/plugins/plugin-package-json.model'
35import { PluginType } from '../../../../shared/models/plugins/plugin.type'
36import { PublicServerSetting } from '../../../../shared/models/plugins/public-server.setting'
37import { ServerConfig } from '../../../../shared/models/server'
38import { User } from '../../../../shared/models/users'
39 33
40const expect = chai.expect 34const expect = chai.expect
41 35
diff --git a/server/tests/api/server/services.ts b/server/tests/api/server/services.ts
index f0fa91674..ea64e4040 100644
--- a/server/tests/api/server/services.ts
+++ b/server/tests/api/server/services.ts
@@ -67,61 +67,67 @@ describe('Test services', function () {
67 }) 67 })
68 68
69 it('Should have a valid oEmbed video response', async function () { 69 it('Should have a valid oEmbed video response', async function () {
70 const oembedUrl = 'http://localhost:' + server.port + '/videos/watch/' + video.uuid 70 for (const basePath of [ '/videos/watch/', '/w/' ]) {
71 71 const oembedUrl = 'http://localhost:' + server.port + basePath + video.uuid
72 const res = await getOEmbed(server.url, oembedUrl) 72
73 const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + 73 const res = await getOEmbed(server.url, oembedUrl)
74 `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + 74 const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' +
75 'frameborder="0" allowfullscreen></iframe>' 75 `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` +
76 const expectedThumbnailUrl = 'http://localhost:' + server.port + video.previewPath 76 'frameborder="0" allowfullscreen></iframe>'
77 77 const expectedThumbnailUrl = 'http://localhost:' + server.port + video.previewPath
78 expect(res.body.html).to.equal(expectedHtml) 78
79 expect(res.body.title).to.equal(video.name) 79 expect(res.body.html).to.equal(expectedHtml)
80 expect(res.body.author_name).to.equal(server.videoChannel.displayName) 80 expect(res.body.title).to.equal(video.name)
81 expect(res.body.width).to.equal(560) 81 expect(res.body.author_name).to.equal(server.videoChannel.displayName)
82 expect(res.body.height).to.equal(315) 82 expect(res.body.width).to.equal(560)
83 expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl) 83 expect(res.body.height).to.equal(315)
84 expect(res.body.thumbnail_width).to.equal(850) 84 expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl)
85 expect(res.body.thumbnail_height).to.equal(480) 85 expect(res.body.thumbnail_width).to.equal(850)
86 expect(res.body.thumbnail_height).to.equal(480)
87 }
86 }) 88 })
87 89
88 it('Should have a valid playlist oEmbed response', async function () { 90 it('Should have a valid playlist oEmbed response', async function () {
89 const oembedUrl = 'http://localhost:' + server.port + '/videos/watch/playlist/' + playlistUUID 91 for (const basePath of [ '/videos/watch/playlist/', '/w/p/' ]) {
90 92 const oembedUrl = 'http://localhost:' + server.port + basePath + playlistUUID
91 const res = await getOEmbed(server.url, oembedUrl) 93
92 const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + 94 const res = await getOEmbed(server.url, oembedUrl)
93 `title="${playlistDisplayName}" src="http://localhost:${server.port}/video-playlists/embed/${playlistUUID}" ` + 95 const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' +
94 'frameborder="0" allowfullscreen></iframe>' 96 `title="${playlistDisplayName}" src="http://localhost:${server.port}/video-playlists/embed/${playlistUUID}" ` +
95 97 'frameborder="0" allowfullscreen></iframe>'
96 expect(res.body.html).to.equal(expectedHtml) 98
97 expect(res.body.title).to.equal('The Life and Times of Scrooge McDuck') 99 expect(res.body.html).to.equal(expectedHtml)
98 expect(res.body.author_name).to.equal(server.videoChannel.displayName) 100 expect(res.body.title).to.equal('The Life and Times of Scrooge McDuck')
99 expect(res.body.width).to.equal(560) 101 expect(res.body.author_name).to.equal(server.videoChannel.displayName)
100 expect(res.body.height).to.equal(315) 102 expect(res.body.width).to.equal(560)
101 expect(res.body.thumbnail_url).exist 103 expect(res.body.height).to.equal(315)
102 expect(res.body.thumbnail_width).to.equal(280) 104 expect(res.body.thumbnail_url).exist
103 expect(res.body.thumbnail_height).to.equal(157) 105 expect(res.body.thumbnail_width).to.equal(280)
106 expect(res.body.thumbnail_height).to.equal(157)
107 }
104 }) 108 })
105 109
106 it('Should have a valid oEmbed response with small max height query', async function () { 110 it('Should have a valid oEmbed response with small max height query', async function () {
107 const oembedUrl = 'http://localhost:' + server.port + '/videos/watch/' + video.uuid 111 for (const basePath of [ '/videos/watch/', '/w/' ]) {
108 const format = 'json' 112 const oembedUrl = 'http://localhost:' + server.port + basePath + video.uuid
109 const maxHeight = 50 113 const format = 'json'
110 const maxWidth = 50 114 const maxHeight = 50
111 115 const maxWidth = 50
112 const res = await getOEmbed(server.url, oembedUrl, format, maxHeight, maxWidth) 116
113 const expectedHtml = '<iframe width="50" height="50" sandbox="allow-same-origin allow-scripts" ' + 117 const res = await getOEmbed(server.url, oembedUrl, format, maxHeight, maxWidth)
114 `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + 118 const expectedHtml = '<iframe width="50" height="50" sandbox="allow-same-origin allow-scripts" ' +
115 'frameborder="0" allowfullscreen></iframe>' 119 `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` +
116 120 'frameborder="0" allowfullscreen></iframe>'
117 expect(res.body.html).to.equal(expectedHtml) 121
118 expect(res.body.title).to.equal(video.name) 122 expect(res.body.html).to.equal(expectedHtml)
119 expect(res.body.author_name).to.equal(server.videoChannel.displayName) 123 expect(res.body.title).to.equal(video.name)
120 expect(res.body.height).to.equal(50) 124 expect(res.body.author_name).to.equal(server.videoChannel.displayName)
121 expect(res.body.width).to.equal(50) 125 expect(res.body.height).to.equal(50)
122 expect(res.body).to.not.have.property('thumbnail_url') 126 expect(res.body.width).to.equal(50)
123 expect(res.body).to.not.have.property('thumbnail_width') 127 expect(res.body).to.not.have.property('thumbnail_url')
124 expect(res.body).to.not.have.property('thumbnail_height') 128 expect(res.body).to.not.have.property('thumbnail_width')
129 expect(res.body).to.not.have.property('thumbnail_height')
130 }
125 }) 131 })
126 132
127 after(async function () { 133 after(async function () {
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index 41cd814e0..6aa996038 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -1,11 +1,10 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2 2
3import * as chai from 'chai'
4import 'mocha' 3import 'mocha'
4import * as chai from 'chai'
5import { join } from 'path' 5import { join } from 'path'
6import * as request from 'supertest' 6import * as request from 'supertest'
7import { VideoPrivacy } from '../../../../shared/models/videos' 7import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
9import { 8import {
10 addVideoChannel, 9 addVideoChannel,
11 checkTmpIsEmpty, 10 checkTmpIsEmpty,
@@ -32,16 +31,16 @@ import {
32 wait, 31 wait,
33 webtorrentAdd 32 webtorrentAdd
34} from '../../../../shared/extra-utils' 33} from '../../../../shared/extra-utils'
34import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
35import { 35import {
36 addVideoCommentReply, 36 addVideoCommentReply,
37 addVideoCommentThread, 37 addVideoCommentThread,
38 deleteVideoComment, 38 deleteVideoComment,
39 findCommentId,
39 getVideoCommentThreads, 40 getVideoCommentThreads,
40 getVideoThreadComments, 41 getVideoThreadComments
41 findCommentId
42} from '../../../../shared/extra-utils/videos/video-comments' 42} from '../../../../shared/extra-utils/videos/video-comments'
43import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 43import { VideoComment, VideoCommentThreadTree, VideoPrivacy } from '../../../../shared/models/videos'
44import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
45 44
46const expect = chai.expect 45const expect = chai.expect
47 46
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts
index 615e0ea45..a5ff3a39d 100644
--- a/server/tests/api/videos/video-comments.ts
+++ b/server/tests/api/videos/video-comments.ts
@@ -2,7 +2,7 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5 5import { VideoComment, VideoCommentAdmin, VideoCommentThreadTree } from '@shared/models'
6import { cleanupTests, testImage } from '../../../../shared/extra-utils' 6import { cleanupTests, testImage } from '../../../../shared/extra-utils'
7import { 7import {
8 createUser, 8 createUser,
@@ -22,7 +22,6 @@ import {
22 getVideoCommentThreads, 22 getVideoCommentThreads,
23 getVideoThreadComments 23 getVideoThreadComments
24} from '../../../../shared/extra-utils/videos/video-comments' 24} from '../../../../shared/extra-utils/videos/video-comments'
25import { VideoComment, VideoCommentAdmin, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model'
26 25
27const expect = chai.expect 26const expect = chai.expect
28 27
diff --git a/server/tests/client.ts b/server/tests/client.ts
index 3c99bcd1f..253a95624 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -2,8 +2,10 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { omit } from 'lodash'
5import * as request from 'supertest' 6import * as request from 'supertest'
6import { Account, VideoPlaylistPrivacy } from '@shared/models' 7import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
8import { Account, CustomConfig, HTMLServerConfig, ServerConfig, VideoPlaylistPrivacy } from '@shared/models'
7import { 9import {
8 addVideoInPlaylist, 10 addVideoInPlaylist,
9 cleanupTests, 11 cleanupTests,
@@ -11,8 +13,10 @@ import {
11 doubleFollow, 13 doubleFollow,
12 flushAndRunMultipleServers, 14 flushAndRunMultipleServers,
13 getAccount, 15 getAccount,
16 getConfig,
14 getCustomConfig, 17 getCustomConfig,
15 getVideosList, 18 getVideosList,
19 makeGetRequest,
16 makeHTMLRequest, 20 makeHTMLRequest,
17 ServerInfo, 21 ServerInfo,
18 setAccessTokensToServers, 22 setAccessTokensToServers,
@@ -24,14 +28,16 @@ import {
24 uploadVideo, 28 uploadVideo,
25 waitJobs 29 waitJobs
26} from '../../shared/extra-utils' 30} from '../../shared/extra-utils'
27import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
28 31
29const expect = chai.expect 32const expect = chai.expect
30 33
31function checkIndexTags (html: string, title: string, description: string, css: string) { 34function checkIndexTags (html: string, title: string, description: string, css: string, config: ServerConfig) {
32 expect(html).to.contain('<title>' + title + '</title>') 35 expect(html).to.contain('<title>' + title + '</title>')
33 expect(html).to.contain('<meta name="description" content="' + description + '" />') 36 expect(html).to.contain('<meta name="description" content="' + description + '" />')
34 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>') 37 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>')
38
39 const htmlConfig: HTMLServerConfig = omit(config, 'signup')
40 expect(html).to.contain(`<script type="application/javascript">window.PeerTubeServerConfig = '${JSON.stringify(htmlConfig)}'</script>`)
35} 41}
36 42
37describe('Test a client controllers', function () { 43describe('Test a client controllers', function () {
@@ -48,6 +54,9 @@ describe('Test a client controllers', function () {
48 54
49 const channelDescription = 'my super channel description' 55 const channelDescription = 'my super channel description'
50 56
57 const watchVideoBasePaths = [ '/videos/watch/', '/w/' ]
58 const watchPlaylistBasePaths = [ '/videos/watch/playlist/', '/w/p/' ]
59
51 before(async function () { 60 before(async function () {
52 this.timeout(120000) 61 this.timeout(120000)
53 62
@@ -105,201 +114,258 @@ describe('Test a client controllers', function () {
105 }) 114 })
106 115
107 describe('oEmbed', function () { 116 describe('oEmbed', function () {
117
108 it('Should have valid oEmbed discovery tags for videos', async function () { 118 it('Should have valid oEmbed discovery tags for videos', async function () {
109 const path = '/videos/watch/' + servers[0].video.uuid 119 for (const basePath of watchVideoBasePaths) {
110 const res = await request(servers[0].url) 120 const path = basePath + servers[0].video.uuid
111 .get(path) 121 const res = await request(servers[0].url)
112 .set('Accept', 'text/html') 122 .get(path)
113 .expect(HttpStatusCode.OK_200) 123 .set('Accept', 'text/html')
124 .expect(HttpStatusCode.OK_200)
114 125
115 const port = servers[0].port 126 const port = servers[0].port
116 127
117 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' + 128 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
118 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2F${servers[0].video.uuid}" ` + 129 `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2F${servers[0].video.uuid}" ` +
119 `title="${servers[0].video.name}" />` 130 `title="${servers[0].video.name}" />`
120 131
121 expect(res.text).to.contain(expectedLink) 132 expect(res.text).to.contain(expectedLink)
133 }
122 }) 134 })
123 135
124 it('Should have valid oEmbed discovery tags for a playlist', async function () { 136 it('Should have valid oEmbed discovery tags for a playlist', async function () {
125 const res = await request(servers[0].url) 137 for (const basePath of watchPlaylistBasePaths) {
126 .get('/videos/watch/playlist/' + playlistUUID) 138 const res = await request(servers[0].url)
127 .set('Accept', 'text/html') 139 .get(basePath + playlistUUID)
128 .expect(HttpStatusCode.OK_200) 140 .set('Accept', 'text/html')
141 .expect(HttpStatusCode.OK_200)
129 142
130 const port = servers[0].port 143 const port = servers[0].port
131 144
132 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' + 145 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
133 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2Fplaylist%2F${playlistUUID}" ` + 146 `url=http%3A%2F%2Flocalhost%3A${port}%2Fw%2Fp%2F${playlistUUID}" ` +
134 `title="${playlistName}" />` 147 `title="${playlistName}" />`
135 148
136 expect(res.text).to.contain(expectedLink) 149 expect(res.text).to.contain(expectedLink)
150 }
137 }) 151 })
138 }) 152 })
139 153
140 describe('Open Graph', function () { 154 describe('Open Graph', function () {
141 155
142 it('Should have valid Open Graph tags on the account page', async function () { 156 async function accountPageTest (path: string) {
143 const res = await request(servers[0].url) 157 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
144 .get('/accounts/' + servers[0].user.username) 158 const text = res.text
145 .set('Accept', 'text/html')
146 .expect(HttpStatusCode.OK_200)
147
148 expect(res.text).to.contain(`<meta property="og:title" content="${account.displayName}" />`)
149 expect(res.text).to.contain(`<meta property="og:description" content="${account.description}" />`)
150 expect(res.text).to.contain('<meta property="og:type" content="website" />')
151 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/accounts/${servers[0].user.username}" />`)
152 })
153 159
154 it('Should have valid Open Graph tags on the channel page', async function () { 160 expect(text).to.contain(`<meta property="og:title" content="${account.displayName}" />`)
155 const res = await request(servers[0].url) 161 expect(text).to.contain(`<meta property="og:description" content="${account.description}" />`)
156 .get('/video-channels/' + servers[0].videoChannel.name) 162 expect(text).to.contain('<meta property="og:type" content="website" />')
157 .set('Accept', 'text/html') 163 expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/accounts/${servers[0].user.username}" />`)
158 .expect(HttpStatusCode.OK_200) 164 }
159 165
160 expect(res.text).to.contain(`<meta property="og:title" content="${servers[0].videoChannel.displayName}" />`) 166 async function channelPageTest (path: string) {
161 expect(res.text).to.contain(`<meta property="og:description" content="${channelDescription}" />`) 167 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
162 expect(res.text).to.contain('<meta property="og:type" content="website" />') 168 const text = res.text
163 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/video-channels/${servers[0].videoChannel.name}" />`)
164 })
165 169
166 it('Should have valid Open Graph tags on the watch page with video id', async function () { 170 expect(text).to.contain(`<meta property="og:title" content="${servers[0].videoChannel.displayName}" />`)
167 const res = await request(servers[0].url) 171 expect(text).to.contain(`<meta property="og:description" content="${channelDescription}" />`)
168 .get('/videos/watch/' + servers[0].video.id) 172 expect(text).to.contain('<meta property="og:type" content="website" />')
169 .set('Accept', 'text/html') 173 expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/video-channels/${servers[0].videoChannel.name}" />`)
170 .expect(HttpStatusCode.OK_200) 174 }
175
176 async function watchVideoPageTest (path: string) {
177 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
178 const text = res.text
179
180 expect(text).to.contain(`<meta property="og:title" content="${videoName}" />`)
181 expect(text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`)
182 expect(text).to.contain('<meta property="og:type" content="video" />')
183 expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/${servers[0].video.uuid}" />`)
184 }
171 185
172 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) 186 async function watchPlaylistPageTest (path: string) {
173 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`) 187 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
174 expect(res.text).to.contain('<meta property="og:type" content="video" />') 188 const text = res.text
175 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) 189
190 expect(text).to.contain(`<meta property="og:title" content="${playlistName}" />`)
191 expect(text).to.contain(`<meta property="og:description" content="${playlistDescription}" />`)
192 expect(text).to.contain('<meta property="og:type" content="video" />')
193 expect(text).to.contain(`<meta property="og:url" content="${servers[0].url}/w/p/${playlistUUID}" />`)
194 }
195
196 it('Should have valid Open Graph tags on the account page', async function () {
197 await accountPageTest('/accounts/' + servers[0].user.username)
198 await accountPageTest('/a/' + servers[0].user.username)
199 await accountPageTest('/@' + servers[0].user.username)
176 }) 200 })
177 201
178 it('Should have valid Open Graph tags on the watch page with video uuid', async function () { 202 it('Should have valid Open Graph tags on the channel page', async function () {
179 const res = await request(servers[0].url) 203 await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
180 .get('/videos/watch/' + servers[0].video.uuid) 204 await channelPageTest('/c/' + servers[0].videoChannel.name)
181 .set('Accept', 'text/html') 205 await channelPageTest('/@' + servers[0].videoChannel.name)
182 .expect(HttpStatusCode.OK_200) 206 })
183 207
184 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) 208 it('Should have valid Open Graph tags on the watch page', async function () {
185 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`) 209 await watchVideoPageTest('/videos/watch/' + servers[0].video.id)
186 expect(res.text).to.contain('<meta property="og:type" content="video" />') 210 await watchVideoPageTest('/videos/watch/' + servers[0].video.uuid)
187 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) 211 await watchVideoPageTest('/w/' + servers[0].video.uuid)
212 await watchVideoPageTest('/w/' + servers[0].video.id)
188 }) 213 })
189 214
190 it('Should have valid Open Graph tags on the watch playlist page', async function () { 215 it('Should have valid Open Graph tags on the watch playlist page', async function () {
191 const res = await request(servers[0].url) 216 await watchPlaylistPageTest('/videos/watch/playlist/' + playlistUUID)
192 .get('/videos/watch/playlist/' + playlistUUID) 217 await watchPlaylistPageTest('/w/p/' + playlistUUID)
193 .set('Accept', 'text/html')
194 .expect(HttpStatusCode.OK_200)
195
196 expect(res.text).to.contain(`<meta property="og:title" content="${playlistName}" />`)
197 expect(res.text).to.contain(`<meta property="og:description" content="${playlistDescription}" />`)
198 expect(res.text).to.contain('<meta property="og:type" content="video" />')
199 expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/playlist/${playlistUUID}" />`)
200 }) 218 })
201 }) 219 })
202 220
203 describe('Twitter card', async function () { 221 describe('Twitter card', async function () {
204 222
205 it('Should have valid twitter card on the watch video page', async function () { 223 describe('Not whitelisted', function () {
206 const res = await request(servers[0].url)
207 .get('/videos/watch/' + servers[0].video.uuid)
208 .set('Accept', 'text/html')
209 .expect(HttpStatusCode.OK_200)
210 224
211 expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />') 225 async function accountPageTest (path: string) {
212 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') 226 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
213 expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`) 227 const text = res.text
214 expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescriptionPlainText}" />`) 228
215 }) 229 expect(text).to.contain('<meta property="twitter:card" content="summary" />')
230 expect(text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
231 expect(text).to.contain(`<meta property="twitter:title" content="${account.name}" />`)
232 expect(text).to.contain(`<meta property="twitter:description" content="${account.description}" />`)
233 }
216 234
217 it('Should have valid twitter card on the watch playlist page', async function () { 235 async function channelPageTest (path: string) {
218 const res = await request(servers[0].url) 236 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
219 .get('/videos/watch/playlist/' + playlistUUID) 237 const text = res.text
220 .set('Accept', 'text/html')
221 .expect(HttpStatusCode.OK_200)
222 238
223 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />') 239 expect(text).to.contain('<meta property="twitter:card" content="summary" />')
224 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') 240 expect(text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
225 expect(res.text).to.contain(`<meta property="twitter:title" content="${playlistName}" />`) 241 expect(text).to.contain(`<meta property="twitter:title" content="${servers[0].videoChannel.displayName}" />`)
226 expect(res.text).to.contain(`<meta property="twitter:description" content="${playlistDescription}" />`) 242 expect(text).to.contain(`<meta property="twitter:description" content="${channelDescription}" />`)
227 }) 243 }
228 244
229 it('Should have valid twitter card on the account page', async function () { 245 async function watchVideoPageTest (path: string) {
230 const res = await request(servers[0].url) 246 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
231 .get('/accounts/' + account.name) 247 const text = res.text
232 .set('Accept', 'text/html')
233 .expect(HttpStatusCode.OK_200)
234 248
235 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />') 249 expect(text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
236 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') 250 expect(text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
237 expect(res.text).to.contain(`<meta property="twitter:title" content="${account.name}" />`) 251 expect(text).to.contain(`<meta property="twitter:title" content="${videoName}" />`)
238 expect(res.text).to.contain(`<meta property="twitter:description" content="${account.description}" />`) 252 expect(text).to.contain(`<meta property="twitter:description" content="${videoDescriptionPlainText}" />`)
239 }) 253 }
254
255 async function watchPlaylistPageTest (path: string) {
256 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
257 const text = res.text
240 258
241 it('Should have valid twitter card on the channel page', async function () { 259 expect(text).to.contain('<meta property="twitter:card" content="summary" />')
242 const res = await request(servers[0].url) 260 expect(text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
243 .get('/video-channels/' + servers[0].videoChannel.name) 261 expect(text).to.contain(`<meta property="twitter:title" content="${playlistName}" />`)
244 .set('Accept', 'text/html') 262 expect(text).to.contain(`<meta property="twitter:description" content="${playlistDescription}" />`)
245 .expect(HttpStatusCode.OK_200) 263 }
246 264
247 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />') 265 it('Should have valid twitter card on the watch video page', async function () {
248 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') 266 await watchVideoPageTest('/videos/watch/' + servers[0].video.id)
249 expect(res.text).to.contain(`<meta property="twitter:title" content="${servers[0].videoChannel.displayName}" />`) 267 await watchVideoPageTest('/videos/watch/' + servers[0].video.uuid)
250 expect(res.text).to.contain(`<meta property="twitter:description" content="${channelDescription}" />`) 268 await watchVideoPageTest('/w/' + servers[0].video.uuid)
269 await watchVideoPageTest('/w/' + servers[0].video.id)
270 })
271
272 it('Should have valid twitter card on the watch playlist page', async function () {
273 await watchPlaylistPageTest('/videos/watch/playlist/' + playlistUUID)
274 await watchPlaylistPageTest('/w/p/' + playlistUUID)
275 })
276
277 it('Should have valid twitter card on the account page', async function () {
278 await accountPageTest('/accounts/' + account.name)
279 await accountPageTest('/a/' + account.name)
280 await accountPageTest('/@' + account.name)
281 })
282
283 it('Should have valid twitter card on the channel page', async function () {
284 await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
285 await channelPageTest('/c/' + servers[0].videoChannel.name)
286 await channelPageTest('/@' + servers[0].videoChannel.name)
287 })
251 }) 288 })
252 289
253 it('Should have valid twitter card if Twitter is whitelisted', async function () { 290 describe('Whitelisted', function () {
254 const res1 = await getCustomConfig(servers[0].url, servers[0].accessToken) 291
255 const config = res1.body 292 before(async function () {
256 config.services.twitter = { 293 const res = await getCustomConfig(servers[0].url, servers[0].accessToken)
257 username: '@Kuja', 294 const config = res.body as CustomConfig
258 whitelisted: true 295 config.services.twitter = {
296 username: '@Kuja',
297 whitelisted: true
298 }
299
300 await updateCustomConfig(servers[0].url, servers[0].accessToken, config)
301 })
302
303 async function accountPageTest (path: string) {
304 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
305 const text = res.text
306
307 expect(text).to.contain('<meta property="twitter:card" content="summary" />')
308 expect(text).to.contain('<meta property="twitter:site" content="@Kuja" />')
259 } 309 }
260 await updateCustomConfig(servers[0].url, servers[0].accessToken, config)
261 310
262 const resVideoRequest = await request(servers[0].url) 311 async function channelPageTest (path: string) {
263 .get('/videos/watch/' + servers[0].video.uuid) 312 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
264 .set('Accept', 'text/html') 313 const text = res.text
265 .expect(HttpStatusCode.OK_200)
266 314
267 expect(resVideoRequest.text).to.contain('<meta property="twitter:card" content="player" />') 315 expect(text).to.contain('<meta property="twitter:card" content="summary" />')
268 expect(resVideoRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />') 316 expect(text).to.contain('<meta property="twitter:site" content="@Kuja" />')
317 }
318
319 async function watchVideoPageTest (path: string) {
320 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
321 const text = res.text
322
323 expect(text).to.contain('<meta property="twitter:card" content="player" />')
324 expect(text).to.contain('<meta property="twitter:site" content="@Kuja" />')
325 }
269 326
270 const resVideoPlaylistRequest = await request(servers[0].url) 327 async function watchPlaylistPageTest (path: string) {
271 .get('/videos/watch/playlist/' + playlistUUID) 328 const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', statusCodeExpected: HttpStatusCode.OK_200 })
272 .set('Accept', 'text/html') 329 const text = res.text
273 .expect(HttpStatusCode.OK_200)
274 330
275 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:card" content="player" />') 331 expect(text).to.contain('<meta property="twitter:card" content="player" />')
276 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />') 332 expect(text).to.contain('<meta property="twitter:site" content="@Kuja" />')
333 }
277 334
278 const resAccountRequest = await request(servers[0].url) 335 it('Should have valid twitter card on the watch video page', async function () {
279 .get('/accounts/' + account.name) 336 await watchVideoPageTest('/videos/watch/' + servers[0].video.id)
280 .set('Accept', 'text/html') 337 await watchVideoPageTest('/videos/watch/' + servers[0].video.uuid)
281 .expect(HttpStatusCode.OK_200) 338 await watchVideoPageTest('/w/' + servers[0].video.uuid)
339 await watchVideoPageTest('/w/' + servers[0].video.id)
340 })
282 341
283 expect(resAccountRequest.text).to.contain('<meta property="twitter:card" content="summary" />') 342 it('Should have valid twitter card on the watch playlist page', async function () {
284 expect(resAccountRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />') 343 await watchPlaylistPageTest('/videos/watch/playlist/' + playlistUUID)
344 await watchPlaylistPageTest('/w/p/' + playlistUUID)
345 })
285 346
286 const resChannelRequest = await request(servers[0].url) 347 it('Should have valid twitter card on the account page', async function () {
287 .get('/video-channels/' + servers[0].videoChannel.name) 348 await accountPageTest('/accounts/' + account.name)
288 .set('Accept', 'text/html') 349 await accountPageTest('/a/' + account.name)
289 .expect(HttpStatusCode.OK_200) 350 await accountPageTest('/@' + account.name)
351 })
290 352
291 expect(resChannelRequest.text).to.contain('<meta property="twitter:card" content="summary" />') 353 it('Should have valid twitter card on the channel page', async function () {
292 expect(resChannelRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />') 354 await channelPageTest('/video-channels/' + servers[0].videoChannel.name)
355 await channelPageTest('/c/' + servers[0].videoChannel.name)
356 await channelPageTest('/@' + servers[0].videoChannel.name)
357 })
293 }) 358 })
294 }) 359 })
295 360
296 describe('Index HTML', function () { 361 describe('Index HTML', function () {
297 362
298 it('Should have valid index html tags (title, description...)', async function () { 363 it('Should have valid index html tags (title, description...)', async function () {
364 const resConfig = await getConfig(servers[0].url)
299 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 365 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
300 366
301 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.' 367 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
302 checkIndexTags(res.text, 'PeerTube', description, '') 368 checkIndexTags(res.text, 'PeerTube', description, '', resConfig.body)
303 }) 369 })
304 370
305 it('Should update the customized configuration and have the correct index html tags', async function () { 371 it('Should update the customized configuration and have the correct index html tags', async function () {
@@ -318,35 +384,61 @@ describe('Test a client controllers', function () {
318 } 384 }
319 }) 385 })
320 386
387 const resConfig = await getConfig(servers[0].url)
321 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 388 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
322 389
323 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }') 390 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
324 }) 391 })
325 392
326 it('Should have valid index html updated tags (title, description...)', async function () { 393 it('Should have valid index html updated tags (title, description...)', async function () {
394 const resConfig = await getConfig(servers[0].url)
327 const res = await makeHTMLRequest(servers[0].url, '/videos/trending') 395 const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
328 396
329 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }') 397 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
330 }) 398 })
331 399
332 it('Should use the original video URL for the canonical tag', async function () { 400 it('Should use the original video URL for the canonical tag', async function () {
333 const res = await makeHTMLRequest(servers[1].url, '/videos/watch/' + servers[0].video.uuid) 401 for (const basePath of watchVideoBasePaths) {
334 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) 402 const res = await makeHTMLRequest(servers[1].url, basePath + servers[0].video.uuid)
403 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`)
404 }
335 }) 405 })
336 406
337 it('Should use the original account URL for the canonical tag', async function () { 407 it('Should use the original account URL for the canonical tag', async function () {
338 const res = await makeHTMLRequest(servers[1].url, '/accounts/root@' + servers[0].host) 408 const accountURLtest = (res) => {
339 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/accounts/root" />`) 409 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/accounts/root" />`)
410 }
411
412 accountURLtest(await makeHTMLRequest(servers[1].url, '/accounts/root@' + servers[0].host))
413 accountURLtest(await makeHTMLRequest(servers[1].url, '/a/root@' + servers[0].host))
414 accountURLtest(await makeHTMLRequest(servers[1].url, '/@root@' + servers[0].host))
340 }) 415 })
341 416
342 it('Should use the original channel URL for the canonical tag', async function () { 417 it('Should use the original channel URL for the canonical tag', async function () {
343 const res = await makeHTMLRequest(servers[1].url, '/video-channels/root_channel@' + servers[0].host) 418 const channelURLtests = (res) => {
344 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/video-channels/root_channel" />`) 419 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/video-channels/root_channel" />`)
420 }
421
422 channelURLtests(await makeHTMLRequest(servers[1].url, '/video-channels/root_channel@' + servers[0].host))
423 channelURLtests(await makeHTMLRequest(servers[1].url, '/c/root_channel@' + servers[0].host))
424 channelURLtests(await makeHTMLRequest(servers[1].url, '/@root_channel@' + servers[0].host))
345 }) 425 })
346 426
347 it('Should use the original playlist URL for the canonical tag', async function () { 427 it('Should use the original playlist URL for the canonical tag', async function () {
348 const res = await makeHTMLRequest(servers[1].url, '/videos/watch/playlist/' + playlistUUID) 428 for (const basePath of watchPlaylistBasePaths) {
349 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/video-playlists/${playlistUUID}" />`) 429 const res = await makeHTMLRequest(servers[1].url, basePath + playlistUUID)
430 expect(res.text).to.contain(`<link rel="canonical" href="${servers[0].url}/video-playlists/${playlistUUID}" />`)
431 }
432 })
433 })
434
435 describe('Embed HTML', function () {
436
437 it('Should have the correct embed html tags', async function () {
438 const resConfig = await getConfig(servers[0].url)
439 const res = await makeHTMLRequest(servers[0].url, servers[0].video.embedPath)
440
441 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', resConfig.body)
350 }) 442 })
351 }) 443 })
352 444
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index 7d4f7abb4..1d6bb6cf4 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -38,6 +38,7 @@ import {
38import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers' 38import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
39import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' 39import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
40import { 40import {
41 VideoCommentThreadTree,
41 VideoDetails, 42 VideoDetails,
42 VideoImport, 43 VideoImport,
43 VideoImportState, 44 VideoImportState,
@@ -45,7 +46,6 @@ import {
45 VideoPlaylistPrivacy, 46 VideoPlaylistPrivacy,
46 VideoPrivacy 47 VideoPrivacy
47} from '../../../shared/models/videos' 48} from '../../../shared/models/videos'
48import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
49 49
50const expect = chai.expect 50const expect = chai.expect
51 51