aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests')
-rw-r--r--server/tests/api/activitypub/security.ts116
-rw-r--r--server/tests/api/check-params/user-notifications.ts4
-rw-r--r--server/tests/api/check-params/users.ts2
-rw-r--r--server/tests/api/notifications/admin-notifications.ts165
-rw-r--r--server/tests/api/notifications/index.ts1
-rw-r--r--server/tests/api/server/handle-down.ts2
-rw-r--r--server/tests/api/users/users.ts51
-rw-r--r--server/tests/cli/index.ts1
-rw-r--r--server/tests/cli/regenerate-thumbnails.ts110
-rw-r--r--server/tests/fixtures/peertube-plugin-test/main.js70
-rw-r--r--server/tests/helpers/request.ts16
-rw-r--r--server/tests/plugins/external-auth.ts2
-rw-r--r--server/tests/plugins/filter-hooks.ts178
13 files changed, 660 insertions, 58 deletions
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts
index 8bde54a40..364b53e0f 100644
--- a/server/tests/api/activitypub/security.ts
+++ b/server/tests/api/activitypub/security.ts
@@ -8,6 +8,8 @@ import {
8 cleanupTests, 8 cleanupTests,
9 closeAllSequelize, 9 closeAllSequelize,
10 flushAndRunMultipleServers, 10 flushAndRunMultipleServers,
11 killallServers,
12 reRunServer,
11 ServerInfo, 13 ServerInfo,
12 setActorField, 14 setActorField,
13 wait 15 wait
@@ -20,21 +22,32 @@ import { buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activi
20const expect = chai.expect 22const expect = chai.expect
21 23
22function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: string, privateKey: string) { 24function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: string, privateKey: string) {
25 const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
26
23 return Promise.all([ 27 return Promise.all([
24 setActorField(onServer.internalServerNumber, 'http://localhost:' + ofServer.port + '/accounts/peertube', 'publicKey', publicKey), 28 setActorField(onServer.internalServerNumber, url, 'publicKey', publicKey),
25 setActorField(onServer.internalServerNumber, 'http://localhost:' + ofServer.port + '/accounts/peertube', 'privateKey', privateKey) 29 setActorField(onServer.internalServerNumber, url, 'privateKey', privateKey)
26 ]) 30 ])
27} 31}
28 32
29function getAnnounceWithoutContext (server2: ServerInfo) { 33function setUpdatedAtOfServer (onServer: ServerInfo, ofServer: ServerInfo, updatedAt: string) {
34 const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
35
36 return Promise.all([
37 setActorField(onServer.internalServerNumber, url, 'createdAt', updatedAt),
38 setActorField(onServer.internalServerNumber, url, 'updatedAt', updatedAt)
39 ])
40}
41
42function getAnnounceWithoutContext (server: ServerInfo) {
30 const json = require('./json/peertube/announce-without-context.json') 43 const json = require('./json/peertube/announce-without-context.json')
31 const result: typeof json = {} 44 const result: typeof json = {}
32 45
33 for (const key of Object.keys(json)) { 46 for (const key of Object.keys(json)) {
34 if (Array.isArray(json[key])) { 47 if (Array.isArray(json[key])) {
35 result[key] = json[key].map(v => v.replace(':9002', `:${server2.port}`)) 48 result[key] = json[key].map(v => v.replace(':9002', `:${server.port}`))
36 } else { 49 } else {
37 result[key] = json[key].replace(':9002', `:${server2.port}`) 50 result[key] = json[key].replace(':9002', `:${server.port}`)
38 } 51 }
39 } 52 }
40 53
@@ -64,7 +77,8 @@ describe('Test ActivityPub security', function () {
64 77
65 url = servers[0].url + '/inbox' 78 url = servers[0].url + '/inbox'
66 79
67 await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey) 80 await setKeysOfServer(servers[0], servers[1], keys.publicKey, null)
81 await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
68 82
69 const to = { url: 'http://localhost:' + servers[0].port + '/accounts/peertube' } 83 const to = { url: 'http://localhost:' + servers[0].port + '/accounts/peertube' }
70 const by = { url: 'http://localhost:' + servers[1].port + '/accounts/peertube', privateKey: keys.privateKey } 84 const by = { url: 'http://localhost:' + servers[1].port + '/accounts/peertube', privateKey: keys.privateKey }
@@ -79,9 +93,12 @@ describe('Test ActivityPub security', function () {
79 Digest: buildDigest({ hello: 'coucou' }) 93 Digest: buildDigest({ hello: 'coucou' })
80 } 94 }
81 95
82 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers) 96 try {
83 97 await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
84 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 98 expect(true, 'Did not throw').to.be.false
99 } catch (err) {
100 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
101 }
85 }) 102 })
86 103
87 it('Should fail with an invalid date', async function () { 104 it('Should fail with an invalid date', async function () {
@@ -89,9 +106,12 @@ describe('Test ActivityPub security', function () {
89 const headers = buildGlobalHeaders(body) 106 const headers = buildGlobalHeaders(body)
90 headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT' 107 headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
91 108
92 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers) 109 try {
93 110 await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
94 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 111 expect(true, 'Did not throw').to.be.false
112 } catch (err) {
113 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
114 }
95 }) 115 })
96 116
97 it('Should fail with bad keys', async function () { 117 it('Should fail with bad keys', async function () {
@@ -101,9 +121,12 @@ describe('Test ActivityPub security', function () {
101 const body = activityPubContextify(getAnnounceWithoutContext(servers[1])) 121 const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
102 const headers = buildGlobalHeaders(body) 122 const headers = buildGlobalHeaders(body)
103 123
104 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers) 124 try {
105 125 await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
106 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 126 expect(true, 'Did not throw').to.be.false
127 } catch (err) {
128 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
129 }
107 }) 130 })
108 131
109 it('Should reject requests without appropriate signed headers', async function () { 132 it('Should reject requests without appropriate signed headers', async function () {
@@ -123,8 +146,12 @@ describe('Test ActivityPub security', function () {
123 for (const badHeaders of badHeadersMatrix) { 146 for (const badHeaders of badHeadersMatrix) {
124 signatureOptions.headers = badHeaders 147 signatureOptions.headers = badHeaders
125 148
126 const { response } = await makePOSTAPRequest(url, body, signatureOptions, headers) 149 try {
127 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 150 await makePOSTAPRequest(url, body, signatureOptions, headers)
151 expect(true, 'Did not throw').to.be.false
152 } catch (err) {
153 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
154 }
128 } 155 }
129 }) 156 })
130 157
@@ -132,27 +159,32 @@ describe('Test ActivityPub security', function () {
132 const body = activityPubContextify(getAnnounceWithoutContext(servers[1])) 159 const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
133 const headers = buildGlobalHeaders(body) 160 const headers = buildGlobalHeaders(body)
134 161
135 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers) 162 const { statusCode } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
136 163 expect(statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
137 expect(response.statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
138 }) 164 })
139 165
140 it('Should refresh the actor keys', async function () { 166 it('Should refresh the actor keys', async function () {
141 this.timeout(20000) 167 this.timeout(20000)
142 168
143 // Wait refresh invalidation
144 await wait(10000)
145
146 // Update keys of server 2 to invalid keys 169 // Update keys of server 2 to invalid keys
147 // Server 1 should refresh the actor and fail 170 // Server 1 should refresh the actor and fail
148 await setKeysOfServer(servers[1], servers[1], invalidKeys.publicKey, invalidKeys.privateKey) 171 await setKeysOfServer(servers[1], servers[1], invalidKeys.publicKey, invalidKeys.privateKey)
172 await setUpdatedAtOfServer(servers[0], servers[1], '2015-07-17 22:00:00+00')
173
174 // Invalid peertube actor cache
175 killallServers([ servers[1] ])
176 await reRunServer(servers[1])
149 177
150 const body = activityPubContextify(getAnnounceWithoutContext(servers[1])) 178 const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
151 const headers = buildGlobalHeaders(body) 179 const headers = buildGlobalHeaders(body)
152 180
153 const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers) 181 try {
154 182 await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
155 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 183 expect(true, 'Did not throw').to.be.false
184 } catch (err) {
185 console.error(err)
186 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
187 }
156 }) 188 })
157 }) 189 })
158 190
@@ -183,9 +215,12 @@ describe('Test ActivityPub security', function () {
183 215
184 const headers = buildGlobalHeaders(signedBody) 216 const headers = buildGlobalHeaders(signedBody)
185 217
186 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers) 218 try {
187 219 await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
188 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 220 expect(true, 'Did not throw').to.be.false
221 } catch (err) {
222 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
223 }
189 }) 224 })
190 225
191 it('Should fail with an altered body', async function () { 226 it('Should fail with an altered body', async function () {
@@ -204,9 +239,12 @@ describe('Test ActivityPub security', function () {
204 239
205 const headers = buildGlobalHeaders(signedBody) 240 const headers = buildGlobalHeaders(signedBody)
206 241
207 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers) 242 try {
208 243 await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
209 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 244 expect(true, 'Did not throw').to.be.false
245 } catch (err) {
246 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
247 }
210 }) 248 })
211 249
212 it('Should succeed with a valid signature', async function () { 250 it('Should succeed with a valid signature', async function () {
@@ -220,9 +258,8 @@ describe('Test ActivityPub security', function () {
220 258
221 const headers = buildGlobalHeaders(signedBody) 259 const headers = buildGlobalHeaders(signedBody)
222 260
223 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers) 261 const { statusCode } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
224 262 expect(statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
225 expect(response.statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
226 }) 263 })
227 264
228 it('Should refresh the actor keys', async function () { 265 it('Should refresh the actor keys', async function () {
@@ -243,9 +280,12 @@ describe('Test ActivityPub security', function () {
243 280
244 const headers = buildGlobalHeaders(signedBody) 281 const headers = buildGlobalHeaders(signedBody)
245 282
246 const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers) 283 try {
247 284 await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
248 expect(response.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403) 285 expect(true, 'Did not throw').to.be.false
286 } catch (err) {
287 expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
288 }
249 }) 289 })
250 }) 290 })
251 291
diff --git a/server/tests/api/check-params/user-notifications.ts b/server/tests/api/check-params/user-notifications.ts
index 05a78b0ad..26d4423f9 100644
--- a/server/tests/api/check-params/user-notifications.ts
+++ b/server/tests/api/check-params/user-notifications.ts
@@ -176,7 +176,9 @@ describe('Test user notifications API validators', function () {
176 newInstanceFollower: UserNotificationSettingValue.WEB, 176 newInstanceFollower: UserNotificationSettingValue.WEB,
177 autoInstanceFollowing: UserNotificationSettingValue.WEB, 177 autoInstanceFollowing: UserNotificationSettingValue.WEB,
178 abuseNewMessage: UserNotificationSettingValue.WEB, 178 abuseNewMessage: UserNotificationSettingValue.WEB,
179 abuseStateChange: UserNotificationSettingValue.WEB 179 abuseStateChange: UserNotificationSettingValue.WEB,
180 newPeerTubeVersion: UserNotificationSettingValue.WEB,
181 newPluginVersion: UserNotificationSettingValue.WEB
180 } 182 }
181 183
182 it('Should fail with missing fields', async function () { 184 it('Should fail with missing fields', async function () {
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 0a13f5b67..2b03fde2d 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -241,7 +241,7 @@ describe('Test users API validators', function () {
241 }) 241 })
242 242
243 it('Should succeed with no password on a server with smtp enabled', async function () { 243 it('Should succeed with no password on a server with smtp enabled', async function () {
244 this.timeout(10000) 244 this.timeout(20000)
245 245
246 killallServers([ server ]) 246 killallServers([ server ])
247 247
diff --git a/server/tests/api/notifications/admin-notifications.ts b/server/tests/api/notifications/admin-notifications.ts
new file mode 100644
index 000000000..e07327d74
--- /dev/null
+++ b/server/tests/api/notifications/admin-notifications.ts
@@ -0,0 +1,165 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { expect } from 'chai'
5import { MockJoinPeerTubeVersions } from '@shared/extra-utils/mock-servers/joinpeertube-versions'
6import { cleanupTests, installPlugin, setPluginLatestVersion, setPluginVersion, wait } from '../../../../shared/extra-utils'
7import { ServerInfo } from '../../../../shared/extra-utils/index'
8import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
9import {
10 CheckerBaseParams,
11 checkNewPeerTubeVersion,
12 checkNewPluginVersion,
13 prepareNotificationsTest
14} from '../../../../shared/extra-utils/users/user-notifications'
15import { UserNotification, UserNotificationType } from '../../../../shared/models/users'
16import { PluginType } from '@shared/models'
17
18describe('Test admin notifications', function () {
19 let server: ServerInfo
20 let userNotifications: UserNotification[] = []
21 let adminNotifications: UserNotification[] = []
22 let emails: object[] = []
23 let baseParams: CheckerBaseParams
24 let joinPeerTubeServer: MockJoinPeerTubeVersions
25
26 before(async function () {
27 this.timeout(120000)
28
29 const config = {
30 peertube: {
31 check_latest_version: {
32 enabled: true,
33 url: 'http://localhost:42102/versions.json'
34 }
35 },
36 plugins: {
37 index: {
38 enabled: true,
39 check_latest_versions_interval: '5 seconds'
40 }
41 }
42 }
43
44 const res = await prepareNotificationsTest(1, config)
45 emails = res.emails
46 server = res.servers[0]
47
48 userNotifications = res.userNotifications
49 adminNotifications = res.adminNotifications
50
51 baseParams = {
52 server: server,
53 emails,
54 socketNotifications: adminNotifications,
55 token: server.accessToken
56 }
57
58 await installPlugin({
59 url: server.url,
60 accessToken: server.accessToken,
61 npmName: 'peertube-plugin-hello-world'
62 })
63
64 await installPlugin({
65 url: server.url,
66 accessToken: server.accessToken,
67 npmName: 'peertube-theme-background-red'
68 })
69
70 joinPeerTubeServer = new MockJoinPeerTubeVersions()
71 await joinPeerTubeServer.initialize()
72 })
73
74 describe('Latest PeerTube version notification', function () {
75
76 it('Should not send a notification to admins if there is not a new version', async function () {
77 this.timeout(30000)
78
79 joinPeerTubeServer.setLatestVersion('1.4.2')
80
81 await wait(3000)
82 await checkNewPeerTubeVersion(baseParams, '1.4.2', 'absence')
83 })
84
85 it('Should send a notification to admins on new plugin version', async function () {
86 this.timeout(30000)
87
88 joinPeerTubeServer.setLatestVersion('15.4.2')
89
90 await wait(3000)
91 await checkNewPeerTubeVersion(baseParams, '15.4.2', 'presence')
92 })
93
94 it('Should not send the same notification to admins', async function () {
95 this.timeout(30000)
96
97 await wait(3000)
98 expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(1)
99 })
100
101 it('Should not have sent a notification to users', async function () {
102 this.timeout(30000)
103
104 expect(userNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(0)
105 })
106
107 it('Should send a new notification after a new release', async function () {
108 this.timeout(30000)
109
110 joinPeerTubeServer.setLatestVersion('15.4.3')
111
112 await wait(3000)
113 await checkNewPeerTubeVersion(baseParams, '15.4.3', 'presence')
114 expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
115 })
116 })
117
118 describe('Latest plugin version notification', function () {
119
120 it('Should not send a notification to admins if there is no new plugin version', async function () {
121 this.timeout(30000)
122
123 await wait(6000)
124 await checkNewPluginVersion(baseParams, PluginType.PLUGIN, 'hello-world', 'absence')
125 })
126
127 it('Should send a notification to admins on new plugin version', async function () {
128 this.timeout(30000)
129
130 await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
131 await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1')
132 await wait(6000)
133
134 await checkNewPluginVersion(baseParams, PluginType.PLUGIN, 'hello-world', 'presence')
135 })
136
137 it('Should not send the same notification to admins', async function () {
138 this.timeout(30000)
139
140 await wait(6000)
141
142 expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PLUGIN_VERSION)).to.have.lengthOf(1)
143 })
144
145 it('Should not have sent a notification to users', async function () {
146 expect(userNotifications.filter(n => n.type === UserNotificationType.NEW_PLUGIN_VERSION)).to.have.lengthOf(0)
147 })
148
149 it('Should send a new notification after a new plugin release', async function () {
150 this.timeout(30000)
151
152 await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
153 await setPluginLatestVersion(server.internalServerNumber, 'hello-world', '0.0.1')
154 await wait(6000)
155
156 expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
157 })
158 })
159
160 after(async function () {
161 MockSmtpServer.Instance.kill()
162
163 await cleanupTests([ server ])
164 })
165})
diff --git a/server/tests/api/notifications/index.ts b/server/tests/api/notifications/index.ts
index bd07a339e..8caa30a3d 100644
--- a/server/tests/api/notifications/index.ts
+++ b/server/tests/api/notifications/index.ts
@@ -1,3 +1,4 @@
1import './admin-notifications'
1import './comments-notifications' 2import './comments-notifications'
2import './moderation-notifications' 3import './moderation-notifications'
3import './notifications-api' 4import './notifications-api'
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
index 043754e70..f3ba11950 100644
--- a/server/tests/api/server/handle-down.ts
+++ b/server/tests/api/server/handle-down.ts
@@ -348,8 +348,8 @@ describe('Test handle downs', function () {
348 348
349 for (let i = 0; i < 3; i++) { 349 for (let i = 0; i < 3; i++) {
350 await getVideo(servers[1].url, videoIdsServer1[i]) 350 await getVideo(servers[1].url, videoIdsServer1[i])
351 await wait(1000)
352 await waitJobs([ servers[1] ]) 351 await waitJobs([ servers[1] ])
352 await wait(1500)
353 } 353 }
354 354
355 for (const id of videoIdsServer1) { 355 for (const id of videoIdsServer1) {
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 62a59033f..cea98aac7 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -4,10 +4,12 @@ import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { AbuseState, AbuseUpdate, MyUser, User, UserRole, Video, VideoPlaylistType } from '@shared/models' 5import { AbuseState, AbuseUpdate, MyUser, User, UserRole, Video, VideoPlaylistType } from '@shared/models'
6import { CustomConfig } from '@shared/models/server' 6import { CustomConfig } from '@shared/models/server'
7import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
7import { 8import {
8 addVideoCommentThread, 9 addVideoCommentThread,
9 blockUser, 10 blockUser,
10 cleanupTests, 11 cleanupTests,
12 closeAllSequelize,
11 createUser, 13 createUser,
12 deleteMe, 14 deleteMe,
13 flushAndRunServer, 15 flushAndRunServer,
@@ -24,6 +26,7 @@ import {
24 getVideoChannel, 26 getVideoChannel,
25 getVideosList, 27 getVideosList,
26 installPlugin, 28 installPlugin,
29 killallServers,
27 login, 30 login,
28 makePutBodyRequest, 31 makePutBodyRequest,
29 rateVideo, 32 rateVideo,
@@ -31,7 +34,9 @@ import {
31 removeUser, 34 removeUser,
32 removeVideo, 35 removeVideo,
33 reportAbuse, 36 reportAbuse,
37 reRunServer,
34 ServerInfo, 38 ServerInfo,
39 setTokenField,
35 testImage, 40 testImage,
36 unblockUser, 41 unblockUser,
37 updateAbuse, 42 updateAbuse,
@@ -44,10 +49,9 @@ import {
44 waitJobs 49 waitJobs
45} from '../../../../shared/extra-utils' 50} from '../../../../shared/extra-utils'
46import { follow } from '../../../../shared/extra-utils/server/follows' 51import { follow } from '../../../../shared/extra-utils/server/follows'
47import { logout, serverLogin, setAccessTokensToServers } from '../../../../shared/extra-utils/users/login' 52import { logout, refreshToken, setAccessTokensToServers } from '../../../../shared/extra-utils/users/login'
48import { getMyVideos } from '../../../../shared/extra-utils/videos/videos' 53import { getMyVideos } from '../../../../shared/extra-utils/videos/videos'
49import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' 54import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
50import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
51 55
52const expect = chai.expect 56const expect = chai.expect
53 57
@@ -89,6 +93,7 @@ describe('Test users', function () {
89 const client = { id: 'client', secret: server.client.secret } 93 const client = { id: 'client', secret: server.client.secret }
90 const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400) 94 const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400)
91 95
96 expect(res.body.code).to.equal('invalid_client')
92 expect(res.body.error).to.contain('client is invalid') 97 expect(res.body.error).to.contain('client is invalid')
93 }) 98 })
94 99
@@ -96,6 +101,7 @@ describe('Test users', function () {
96 const client = { id: server.client.id, secret: 'coucou' } 101 const client = { id: server.client.id, secret: 'coucou' }
97 const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400) 102 const res = await login(server.url, client, server.user, HttpStatusCode.BAD_REQUEST_400)
98 103
104 expect(res.body.code).to.equal('invalid_client')
99 expect(res.body.error).to.contain('client is invalid') 105 expect(res.body.error).to.contain('client is invalid')
100 }) 106 })
101 }) 107 })
@@ -106,6 +112,7 @@ describe('Test users', function () {
106 const user = { username: 'captain crochet', password: server.user.password } 112 const user = { username: 'captain crochet', password: server.user.password }
107 const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400) 113 const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400)
108 114
115 expect(res.body.code).to.equal('invalid_grant')
109 expect(res.body.error).to.contain('credentials are invalid') 116 expect(res.body.error).to.contain('credentials are invalid')
110 }) 117 })
111 118
@@ -113,6 +120,7 @@ describe('Test users', function () {
113 const user = { username: server.user.username, password: 'mew_three' } 120 const user = { username: server.user.username, password: 'mew_three' }
114 const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400) 121 const res = await login(server.url, server.client, user, HttpStatusCode.BAD_REQUEST_400)
115 122
123 expect(res.body.code).to.equal('invalid_grant')
116 expect(res.body.error).to.contain('credentials are invalid') 124 expect(res.body.error).to.contain('credentials are invalid')
117 }) 125 })
118 126
@@ -245,12 +253,44 @@ describe('Test users', function () {
245 }) 253 })
246 254
247 it('Should be able to login again', async function () { 255 it('Should be able to login again', async function () {
248 server.accessToken = await serverLogin(server) 256 const res = await login(server.url, server.client, server.user)
257 server.accessToken = res.body.access_token
258 server.refreshToken = res.body.refresh_token
259 })
260
261 it('Should be able to get my user information again', async function () {
262 await getMyUserInformation(server.url, server.accessToken)
263 })
264
265 it('Should have an expired access token', async function () {
266 this.timeout(15000)
267
268 await setTokenField(server.internalServerNumber, server.accessToken, 'accessTokenExpiresAt', new Date().toISOString())
269 await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString())
270
271 killallServers([ server ])
272 await reRunServer(server)
273
274 await getMyUserInformation(server.url, server.accessToken, 401)
275 })
276
277 it('Should not be able to refresh an access token with an expired refresh token', async function () {
278 await refreshToken(server, server.refreshToken, 400)
249 }) 279 })
250 280
251 it('Should have an expired access token') 281 it('Should refresh the token', async function () {
282 this.timeout(15000)
283
284 const futureDate = new Date(new Date().getTime() + 1000 * 60).toISOString()
285 await setTokenField(server.internalServerNumber, server.accessToken, 'refreshTokenExpiresAt', futureDate)
252 286
253 it('Should refresh the token') 287 killallServers([ server ])
288 await reRunServer(server)
289
290 const res = await refreshToken(server, server.refreshToken)
291 server.accessToken = res.body.access_token
292 server.refreshToken = res.body.refresh_token
293 })
254 294
255 it('Should be able to get my user information again', async function () { 295 it('Should be able to get my user information again', async function () {
256 await getMyUserInformation(server.url, server.accessToken) 296 await getMyUserInformation(server.url, server.accessToken)
@@ -976,6 +1016,7 @@ describe('Test users', function () {
976 }) 1016 })
977 1017
978 after(async function () { 1018 after(async function () {
1019 await closeAllSequelize([ server ])
979 await cleanupTests([ server ]) 1020 await cleanupTests([ server ])
980 }) 1021 })
981}) 1022})
diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts
index 242589010..7e6eebd17 100644
--- a/server/tests/cli/index.ts
+++ b/server/tests/cli/index.ts
@@ -6,5 +6,6 @@ import './peertube'
6import './plugins' 6import './plugins'
7import './print-transcode-command' 7import './print-transcode-command'
8import './prune-storage' 8import './prune-storage'
9import './regenerate-thumbnails'
9import './reset-password' 10import './reset-password'
10import './update-host' 11import './update-host'
diff --git a/server/tests/cli/regenerate-thumbnails.ts b/server/tests/cli/regenerate-thumbnails.ts
new file mode 100644
index 000000000..56005518a
--- /dev/null
+++ b/server/tests/cli/regenerate-thumbnails.ts
@@ -0,0 +1,110 @@
1import 'mocha'
2import { expect } from 'chai'
3import { writeFile } from 'fs-extra'
4import { basename, join } from 'path'
5import { Video } from '@shared/models'
6import {
7 buildServerDirectory,
8 cleanupTests,
9 doubleFollow,
10 execCLI,
11 flushAndRunMultipleServers,
12 getEnvCli,
13 getVideo,
14 makeRawRequest,
15 ServerInfo,
16 setAccessTokensToServers,
17 uploadVideoAndGetId,
18 waitJobs
19} from '../../../shared/extra-utils'
20import { HttpStatusCode } from '@shared/core-utils'
21
22describe('Test regenerate thumbnails script', function () {
23 let servers: ServerInfo[]
24
25 let video1: Video
26 let video2: Video
27 let remoteVideo: Video
28
29 let thumbnail1Path: string
30 let thumbnailRemotePath: string
31
32 before(async function () {
33 this.timeout(60000)
34
35 servers = await flushAndRunMultipleServers(2)
36 await setAccessTokensToServers(servers)
37
38 await doubleFollow(servers[0], servers[1])
39
40 {
41 const videoUUID1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 1' })).uuid
42 video1 = await (getVideo(servers[0].url, videoUUID1).then(res => res.body))
43
44 thumbnail1Path = join(buildServerDirectory(servers[0], 'thumbnails'), basename(video1.thumbnailPath))
45
46 const videoUUID2 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 2' })).uuid
47 video2 = await (getVideo(servers[0].url, videoUUID2).then(res => res.body))
48 }
49
50 {
51 const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3' })).uuid
52 await waitJobs(servers)
53
54 remoteVideo = await (getVideo(servers[0].url, videoUUID).then(res => res.body))
55
56 thumbnailRemotePath = join(buildServerDirectory(servers[0], 'thumbnails'), basename(remoteVideo.thumbnailPath))
57 }
58
59 await writeFile(thumbnail1Path, '')
60 await writeFile(thumbnailRemotePath, '')
61 })
62
63 it('Should have empty thumbnails', async function () {
64 {
65 const res = await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.OK_200)
66 expect(res.body).to.have.lengthOf(0)
67 }
68
69 {
70 const res = await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.OK_200)
71 expect(res.body).to.not.have.lengthOf(0)
72 }
73
74 {
75 const res = await makeRawRequest(join(servers[0].url, remoteVideo.thumbnailPath), HttpStatusCode.OK_200)
76 expect(res.body).to.have.lengthOf(0)
77 }
78 })
79
80 it('Should regenerate thumbnails from the CLI', async function () {
81 this.timeout(15000)
82
83 const env = getEnvCli(servers[0])
84 await execCLI(`${env} npm run regenerate-thumbnails`)
85 })
86
87 it('Should have regenerated thumbbnails', async function () {
88 {
89 const res1 = await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.OK_200)
90 expect(res1.body).to.not.have.lengthOf(0)
91
92 const res2 = await makeRawRequest(join(servers[0].url, video1.previewPath), HttpStatusCode.OK_200)
93 expect(res2.body).to.not.have.lengthOf(0)
94 }
95
96 {
97 const res = await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.OK_200)
98 expect(res.body).to.not.have.lengthOf(0)
99 }
100
101 {
102 const res = await makeRawRequest(join(servers[0].url, remoteVideo.thumbnailPath), HttpStatusCode.OK_200)
103 expect(res.body).to.have.lengthOf(0)
104 }
105 })
106
107 after(async function () {
108 await cleanupTests(servers)
109 })
110})
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js
index 305d92002..ee0bc39f3 100644
--- a/server/tests/fixtures/peertube-plugin-test/main.js
+++ b/server/tests/fixtures/peertube-plugin-test/main.js
@@ -184,6 +184,76 @@ async function register ({ registerHook, registerSetting, settingsManager, stora
184 return result 184 return result
185 } 185 }
186 }) 186 })
187
188 registerHook({
189 target: 'filter:api.download.torrent.allowed.result',
190 handler: (result, params) => {
191 if (params && params.downloadName.includes('bad torrent')) {
192 return { allowed: false, errorMessage: 'Liu Bei' }
193 }
194
195 return result
196 }
197 })
198
199 registerHook({
200 target: 'filter:api.download.video.allowed.result',
201 handler: (result, params) => {
202 if (params && !params.streamingPlaylist && params.video.name.includes('bad file')) {
203 return { allowed: false, errorMessage: 'Cao Cao' }
204 }
205
206 if (params && params.streamingPlaylist && params.video.name.includes('bad playlist file')) {
207 return { allowed: false, errorMessage: 'Sun Jian' }
208 }
209
210 return result
211 }
212 })
213
214 registerHook({
215 target: 'filter:html.embed.video.allowed.result',
216 handler: (result, params) => {
217 return {
218 allowed: false,
219 html: 'Lu Bu'
220 }
221 }
222 })
223
224 registerHook({
225 target: 'filter:html.embed.video-playlist.allowed.result',
226 handler: (result, params) => {
227 return {
228 allowed: false,
229 html: 'Diao Chan'
230 }
231 }
232 })
233
234 {
235 const searchHooks = [
236 'filter:api.search.videos.local.list.params',
237 'filter:api.search.videos.local.list.result',
238 'filter:api.search.videos.index.list.params',
239 'filter:api.search.videos.index.list.result',
240 'filter:api.search.video-channels.local.list.params',
241 'filter:api.search.video-channels.local.list.result',
242 'filter:api.search.video-channels.index.list.params',
243 'filter:api.search.video-channels.index.list.result',
244 ]
245
246 for (const h of searchHooks) {
247 registerHook({
248 target: h,
249 handler: (obj) => {
250 peertubeHelpers.logger.debug('Run hook %s.', h)
251
252 return obj
253 }
254 })
255 }
256 }
187} 257}
188 258
189async function unregister () { 259async function unregister () {
diff --git a/server/tests/helpers/request.ts b/server/tests/helpers/request.ts
index f8b2d599b..5e77f129e 100644
--- a/server/tests/helpers/request.ts
+++ b/server/tests/helpers/request.ts
@@ -1,11 +1,11 @@
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'
4import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
5import { get4KFileUrl, root, wait } from '../../../shared/extra-utils'
6import { join } from 'path'
7import { pathExists, remove } from 'fs-extra'
8import { expect } from 'chai' 4import { expect } from 'chai'
5import { pathExists, remove } from 'fs-extra'
6import { join } from 'path'
7import { get4KFileUrl, root, wait } from '../../../shared/extra-utils'
8import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
9 9
10describe('Request helpers', function () { 10describe('Request helpers', function () {
11 const destPath1 = join(root(), 'test-output-1.txt') 11 const destPath1 = join(root(), 'test-output-1.txt')
@@ -13,7 +13,7 @@ describe('Request helpers', function () {
13 13
14 it('Should throw an error when the bytes limit is exceeded for request', async function () { 14 it('Should throw an error when the bytes limit is exceeded for request', async function () {
15 try { 15 try {
16 await doRequest({ uri: get4KFileUrl() }, 3) 16 await doRequest(get4KFileUrl(), { bodyKBLimit: 3 })
17 } catch { 17 } catch {
18 return 18 return
19 } 19 }
@@ -23,7 +23,7 @@ describe('Request helpers', function () {
23 23
24 it('Should throw an error when the bytes limit is exceeded for request and save file', async function () { 24 it('Should throw an error when the bytes limit is exceeded for request and save file', async function () {
25 try { 25 try {
26 await doRequestAndSaveToFile({ uri: get4KFileUrl() }, destPath1, 3) 26 await doRequestAndSaveToFile(get4KFileUrl(), destPath1, { bodyKBLimit: 3 })
27 } catch { 27 } catch {
28 28
29 await wait(500) 29 await wait(500)
@@ -35,8 +35,8 @@ describe('Request helpers', function () {
35 }) 35 })
36 36
37 it('Should succeed if the file is below the limit', async function () { 37 it('Should succeed if the file is below the limit', async function () {
38 await doRequest({ uri: get4KFileUrl() }, 5) 38 await doRequest(get4KFileUrl(), { bodyKBLimit: 5 })
39 await doRequestAndSaveToFile({ uri: get4KFileUrl() }, destPath2, 5) 39 await doRequestAndSaveToFile(get4KFileUrl(), destPath2, { bodyKBLimit: 5 })
40 40
41 expect(await pathExists(destPath2)).to.be.true 41 expect(await pathExists(destPath2)).to.be.true
42 }) 42 })
diff --git a/server/tests/plugins/external-auth.ts b/server/tests/plugins/external-auth.ts
index a1b5e8f5d..5addb45c7 100644
--- a/server/tests/plugins/external-auth.ts
+++ b/server/tests/plugins/external-auth.ts
@@ -137,7 +137,7 @@ describe('Test external auth plugins', function () {
137 137
138 await loginUsingExternalToken(server, 'cyan', externalAuthToken, HttpStatusCode.BAD_REQUEST_400) 138 await loginUsingExternalToken(server, 'cyan', externalAuthToken, HttpStatusCode.BAD_REQUEST_400)
139 139
140 await waitUntilLog(server, 'expired external auth token') 140 await waitUntilLog(server, 'expired external auth token', 2)
141 }) 141 })
142 142
143 it('Should auto login Cyan, create the user and use the token', async function () { 143 it('Should auto login Cyan, create the user and use the token', async function () {
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index d88170201..ac958c5f5 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -2,11 +2,15 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels'
5import { ServerConfig } from '@shared/models' 6import { ServerConfig } from '@shared/models'
7import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
6import { 8import {
7 addVideoCommentReply, 9 addVideoCommentReply,
8 addVideoCommentThread, 10 addVideoCommentThread,
11 advancedVideosSearch,
9 createLive, 12 createLive,
13 createVideoPlaylist,
10 doubleFollow, 14 doubleFollow,
11 getAccountVideos, 15 getAccountVideos,
12 getConfig, 16 getConfig,
@@ -15,24 +19,33 @@ import {
15 getVideo, 19 getVideo,
16 getVideoChannelVideos, 20 getVideoChannelVideos,
17 getVideoCommentThreads, 21 getVideoCommentThreads,
22 getVideoPlaylist,
18 getVideosList, 23 getVideosList,
19 getVideosListPagination, 24 getVideosListPagination,
20 getVideoThreadComments, 25 getVideoThreadComments,
21 getVideoWithToken, 26 getVideoWithToken,
22 installPlugin, 27 installPlugin,
28 makeRawRequest,
23 registerUser, 29 registerUser,
24 setAccessTokensToServers, 30 setAccessTokensToServers,
25 setDefaultVideoChannel, 31 setDefaultVideoChannel,
26 updateCustomSubConfig, 32 updateCustomSubConfig,
27 updateVideo, 33 updateVideo,
28 uploadVideo, 34 uploadVideo,
35 uploadVideoAndGetId,
29 waitJobs 36 waitJobs
30} from '../../../shared/extra-utils' 37} from '../../../shared/extra-utils'
31import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../shared/extra-utils/server/servers' 38import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
32import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' 39import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
33import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos' 40import {
41 VideoDetails,
42 VideoImport,
43 VideoImportState,
44 VideoPlaylist,
45 VideoPlaylistPrivacy,
46 VideoPrivacy
47} from '../../../shared/models/videos'
34import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' 48import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
35import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
36 49
37const expect = chai.expect 50const expect = chai.expect
38 51
@@ -355,6 +368,165 @@ describe('Test plugin filter hooks', function () {
355 }) 368 })
356 }) 369 })
357 370
371 describe('Download hooks', function () {
372 const downloadVideos: VideoDetails[] = []
373
374 before(async function () {
375 this.timeout(60000)
376
377 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
378 transcoding: {
379 webtorrent: {
380 enabled: true
381 },
382 hls: {
383 enabled: true
384 }
385 }
386 })
387
388 const uuids: string[] = []
389
390 for (const name of [ 'bad torrent', 'bad file', 'bad playlist file' ]) {
391 const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
392 uuids.push(uuid)
393 }
394
395 await waitJobs(servers)
396
397 for (const uuid of uuids) {
398 const res = await getVideo(servers[0].url, uuid)
399 downloadVideos.push(res.body)
400 }
401 })
402
403 it('Should run filter:api.download.torrent.allowed.result', async function () {
404 const res = await makeRawRequest(downloadVideos[0].files[0].torrentDownloadUrl, 403)
405 expect(res.body.error).to.equal('Liu Bei')
406
407 await makeRawRequest(downloadVideos[1].files[0].torrentDownloadUrl, 200)
408 await makeRawRequest(downloadVideos[2].files[0].torrentDownloadUrl, 200)
409 })
410
411 it('Should run filter:api.download.video.allowed.result', async function () {
412 {
413 const res = await makeRawRequest(downloadVideos[1].files[0].fileDownloadUrl, 403)
414 expect(res.body.error).to.equal('Cao Cao')
415
416 await makeRawRequest(downloadVideos[0].files[0].fileDownloadUrl, 200)
417 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
418 }
419
420 {
421 const res = await makeRawRequest(downloadVideos[2].streamingPlaylists[0].files[0].fileDownloadUrl, 403)
422 expect(res.body.error).to.equal('Sun Jian')
423
424 await makeRawRequest(downloadVideos[2].files[0].fileDownloadUrl, 200)
425
426 await makeRawRequest(downloadVideos[0].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
427 await makeRawRequest(downloadVideos[1].streamingPlaylists[0].files[0].fileDownloadUrl, 200)
428 }
429 })
430 })
431
432 describe('Embed filters', function () {
433 const embedVideos: VideoDetails[] = []
434 const embedPlaylists: VideoPlaylist[] = []
435
436 before(async function () {
437 this.timeout(60000)
438
439 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
440 transcoding: {
441 enabled: false
442 }
443 })
444
445 for (const name of [ 'bad embed', 'good embed' ]) {
446 {
447 const uuid = (await uploadVideoAndGetId({ server: servers[0], videoName: name })).uuid
448 const res = await getVideo(servers[0].url, uuid)
449 embedVideos.push(res.body)
450 }
451
452 {
453 const playlistAttrs = { displayName: name, videoChannelId: servers[0].videoChannel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
454 const res = await createVideoPlaylist({ url: servers[0].url, token: servers[0].accessToken, playlistAttrs })
455
456 const resPlaylist = await getVideoPlaylist(servers[0].url, res.body.videoPlaylist.id)
457 embedPlaylists.push(resPlaylist.body)
458 }
459 }
460 })
461
462 it('Should run filter:html.embed.video.allowed.result', async function () {
463 const res = await makeRawRequest(servers[0].url + embedVideos[0].embedPath, 200)
464 expect(res.text).to.equal('Lu Bu')
465 })
466
467 it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
468 const res = await makeRawRequest(servers[0].url + embedPlaylists[0].embedPath, 200)
469 expect(res.text).to.equal('Diao Chan')
470 })
471 })
472
473 describe('Search filters', function () {
474
475 before(async function () {
476 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
477 search: {
478 searchIndex: {
479 enabled: true,
480 isDefaultSearch: false,
481 disableLocalSearch: false
482 }
483 }
484 })
485 })
486
487 it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
488 await advancedVideosSearch(servers[0].url, {
489 search: 'Sun Quan'
490 })
491
492 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
493 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
494 })
495
496 it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
497 await advancedVideosSearch(servers[0].url, {
498 search: 'Sun Quan',
499 searchTarget: 'search-index'
500 })
501
502 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.params', 1)
503 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.local.list.result', 1)
504 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.params', 1)
505 await waitUntilLog(servers[0], 'Run hook filter:api.search.videos.index.list.result', 1)
506 })
507
508 it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
509 await advancedVideoChannelSearch(servers[0].url, {
510 search: 'Sun Ce'
511 })
512
513 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
514 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
515 })
516
517 it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
518 await advancedVideoChannelSearch(servers[0].url, {
519 search: 'Sun Ce',
520 searchTarget: 'search-index'
521 })
522
523 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.params', 1)
524 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.local.list.result', 1)
525 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.params', 1)
526 await waitUntilLog(servers[0], 'Run hook filter:api.search.video-channels.index.list.result', 1)
527 })
528 })
529
358 after(async function () { 530 after(async function () {
359 await cleanupTests(servers) 531 await cleanupTests(servers)
360 }) 532 })