diff options
Diffstat (limited to 'server/tests')
43 files changed, 1247 insertions, 166 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 | |||
20 | const expect = chai.expect | 22 | const expect = chai.expect |
21 | 23 | ||
22 | function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: string, privateKey: string) { | 24 | function 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 | ||
29 | function getAnnounceWithoutContext (server2: ServerInfo) { | 33 | function 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 | |||
42 | function 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/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index 0dd436426..bc2e6192e 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -234,7 +234,8 @@ describe('Test video channels API validator', function () { | |||
234 | }) | 234 | }) |
235 | }) | 235 | }) |
236 | 236 | ||
237 | describe('When updating video channel avatar', function () { | 237 | describe('When updating video channel avatar/banner', function () { |
238 | const types = [ 'avatar', 'banner' ] | ||
238 | let path: string | 239 | let path: string |
239 | 240 | ||
240 | before(async function () { | 241 | before(async function () { |
@@ -242,48 +243,57 @@ describe('Test video channels API validator', function () { | |||
242 | }) | 243 | }) |
243 | 244 | ||
244 | it('Should fail with an incorrect input file', async function () { | 245 | it('Should fail with an incorrect input file', async function () { |
245 | const fields = {} | 246 | for (const type of types) { |
246 | const attaches = { | 247 | const fields = {} |
247 | avatarfile: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4') | 248 | const attaches = { |
249 | [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4') | ||
250 | } | ||
251 | |||
252 | await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches }) | ||
248 | } | 253 | } |
249 | await makeUploadRequest({ url: server.url, path: path + '/avatar/pick', token: server.accessToken, fields, attaches }) | ||
250 | }) | 254 | }) |
251 | 255 | ||
252 | it('Should fail with a big file', async function () { | 256 | it('Should fail with a big file', async function () { |
253 | const fields = {} | 257 | for (const type of types) { |
254 | const attaches = { | 258 | const fields = {} |
255 | avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png') | 259 | const attaches = { |
260 | [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png') | ||
261 | } | ||
262 | await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches }) | ||
256 | } | 263 | } |
257 | await makeUploadRequest({ url: server.url, path: path + '/avatar/pick', token: server.accessToken, fields, attaches }) | ||
258 | }) | 264 | }) |
259 | 265 | ||
260 | it('Should fail with an unauthenticated user', async function () { | 266 | it('Should fail with an unauthenticated user', async function () { |
261 | const fields = {} | 267 | for (const type of types) { |
262 | const attaches = { | 268 | const fields = {} |
263 | avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png') | 269 | const attaches = { |
270 | [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar.png') | ||
271 | } | ||
272 | await makeUploadRequest({ | ||
273 | url: server.url, | ||
274 | path: `${path}/${type}/pick`, | ||
275 | fields, | ||
276 | attaches, | ||
277 | statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 | ||
278 | }) | ||
264 | } | 279 | } |
265 | await makeUploadRequest({ | ||
266 | url: server.url, | ||
267 | path: path + '/avatar/pick', | ||
268 | fields, | ||
269 | attaches, | ||
270 | statusCodeExpected: HttpStatusCode.UNAUTHORIZED_401 | ||
271 | }) | ||
272 | }) | 280 | }) |
273 | 281 | ||
274 | it('Should succeed with the correct params', async function () { | 282 | it('Should succeed with the correct params', async function () { |
275 | const fields = {} | 283 | for (const type of types) { |
276 | const attaches = { | 284 | const fields = {} |
277 | avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png') | 285 | const attaches = { |
286 | [type + 'file']: join(__dirname, '..', '..', 'fixtures', 'avatar.png') | ||
287 | } | ||
288 | await makeUploadRequest({ | ||
289 | url: server.url, | ||
290 | path: `${path}/${type}/pick`, | ||
291 | token: server.accessToken, | ||
292 | fields, | ||
293 | attaches, | ||
294 | statusCodeExpected: HttpStatusCode.OK_200 | ||
295 | }) | ||
278 | } | 296 | } |
279 | await makeUploadRequest({ | ||
280 | url: server.url, | ||
281 | path: path + '/avatar/pick', | ||
282 | token: server.accessToken, | ||
283 | fields, | ||
284 | attaches, | ||
285 | statusCodeExpected: HttpStatusCode.OK_200 | ||
286 | }) | ||
287 | }) | 297 | }) |
288 | }) | 298 | }) |
289 | 299 | ||
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index 0831f91f0..d48e2a8ee 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts | |||
@@ -255,7 +255,7 @@ describe('Test live', function () { | |||
255 | } | 255 | } |
256 | 256 | ||
257 | it('Should not allow a stream without the appropriate path', async function () { | 257 | it('Should not allow a stream without the appropriate path', async function () { |
258 | this.timeout(30000) | 258 | this.timeout(60000) |
259 | 259 | ||
260 | liveVideo = await createLiveWrapper() | 260 | liveVideo = await createLiveWrapper() |
261 | 261 | ||
@@ -264,14 +264,14 @@ describe('Test live', function () { | |||
264 | }) | 264 | }) |
265 | 265 | ||
266 | it('Should not allow a stream without the appropriate stream key', async function () { | 266 | it('Should not allow a stream without the appropriate stream key', async function () { |
267 | this.timeout(30000) | 267 | this.timeout(60000) |
268 | 268 | ||
269 | const command = sendRTMPStream(rtmpUrl + '/live', 'bad-stream-key') | 269 | const command = sendRTMPStream(rtmpUrl + '/live', 'bad-stream-key') |
270 | await testFfmpegStreamError(command, true) | 270 | await testFfmpegStreamError(command, true) |
271 | }) | 271 | }) |
272 | 272 | ||
273 | it('Should succeed with the correct params', async function () { | 273 | it('Should succeed with the correct params', async function () { |
274 | this.timeout(30000) | 274 | this.timeout(60000) |
275 | 275 | ||
276 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) | 276 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) |
277 | await testFfmpegStreamError(command, false) | 277 | await testFfmpegStreamError(command, false) |
@@ -292,7 +292,7 @@ describe('Test live', function () { | |||
292 | }) | 292 | }) |
293 | 293 | ||
294 | it('Should not allow a stream on a live that was blacklisted', async function () { | 294 | it('Should not allow a stream on a live that was blacklisted', async function () { |
295 | this.timeout(30000) | 295 | this.timeout(60000) |
296 | 296 | ||
297 | liveVideo = await createLiveWrapper() | 297 | liveVideo = await createLiveWrapper() |
298 | 298 | ||
@@ -303,7 +303,7 @@ describe('Test live', function () { | |||
303 | }) | 303 | }) |
304 | 304 | ||
305 | it('Should not allow a stream on a live that was deleted', async function () { | 305 | it('Should not allow a stream on a live that was deleted', async function () { |
306 | this.timeout(30000) | 306 | this.timeout(60000) |
307 | 307 | ||
308 | liveVideo = await createLiveWrapper() | 308 | liveVideo = await createLiveWrapper() |
309 | 309 | ||
diff --git a/server/tests/api/notifications/admin-notifications.ts b/server/tests/api/notifications/admin-notifications.ts new file mode 100644 index 000000000..cfe0bd2bb --- /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 | |||
3 | import 'mocha' | ||
4 | import { expect } from 'chai' | ||
5 | import { MockJoinPeerTubeVersions } from '@shared/extra-utils/mock-servers/joinpeertube-versions' | ||
6 | import { PluginType } from '@shared/models' | ||
7 | import { cleanupTests, installPlugin, setPluginLatestVersion, setPluginVersion, wait } from '../../../../shared/extra-utils' | ||
8 | import { ServerInfo } from '../../../../shared/extra-utils/index' | ||
9 | import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' | ||
10 | import { | ||
11 | CheckerBaseParams, | ||
12 | checkNewPeerTubeVersion, | ||
13 | checkNewPluginVersion, | ||
14 | prepareNotificationsTest | ||
15 | } from '../../../../shared/extra-utils/users/user-notifications' | ||
16 | import { UserNotification, UserNotificationType } from '../../../../shared/models/users' | ||
17 | |||
18 | describe('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 | joinPeerTubeServer = new MockJoinPeerTubeVersions() | ||
30 | const port = await joinPeerTubeServer.initialize() | ||
31 | |||
32 | const config = { | ||
33 | peertube: { | ||
34 | check_latest_version: { | ||
35 | enabled: true, | ||
36 | url: `http://localhost:${port}/versions.json` | ||
37 | } | ||
38 | }, | ||
39 | plugins: { | ||
40 | index: { | ||
41 | enabled: true, | ||
42 | check_latest_versions_interval: '5 seconds' | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | |||
47 | const res = await prepareNotificationsTest(1, config) | ||
48 | emails = res.emails | ||
49 | server = res.servers[0] | ||
50 | |||
51 | userNotifications = res.userNotifications | ||
52 | adminNotifications = res.adminNotifications | ||
53 | |||
54 | baseParams = { | ||
55 | server: server, | ||
56 | emails, | ||
57 | socketNotifications: adminNotifications, | ||
58 | token: server.accessToken | ||
59 | } | ||
60 | |||
61 | await installPlugin({ | ||
62 | url: server.url, | ||
63 | accessToken: server.accessToken, | ||
64 | npmName: 'peertube-plugin-hello-world' | ||
65 | }) | ||
66 | |||
67 | await installPlugin({ | ||
68 | url: server.url, | ||
69 | accessToken: server.accessToken, | ||
70 | npmName: 'peertube-theme-background-red' | ||
71 | }) | ||
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 @@ | |||
1 | import './admin-notifications' | ||
1 | import './comments-notifications' | 2 | import './comments-notifications' |
2 | import './moderation-notifications' | 3 | import './moderation-notifications' |
3 | import './notifications-api' | 4 | import './notifications-api' |
diff --git a/server/tests/api/notifications/moderation-notifications.ts b/server/tests/api/notifications/moderation-notifications.ts index 4c00d97f8..4ce6675b6 100644 --- a/server/tests/api/notifications/moderation-notifications.ts +++ b/server/tests/api/notifications/moderation-notifications.ts | |||
@@ -2,8 +2,9 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import { v4 as uuidv4 } from 'uuid' | 4 | import { v4 as uuidv4 } from 'uuid' |
5 | 5 | import { AbuseState } from '@shared/models' | |
6 | import { | 6 | import { |
7 | addAbuseMessage, | ||
7 | addVideoCommentThread, | 8 | addVideoCommentThread, |
8 | addVideoToBlacklist, | 9 | addVideoToBlacklist, |
9 | cleanupTests, | 10 | cleanupTests, |
@@ -20,18 +21,19 @@ import { | |||
20 | removeVideoFromBlacklist, | 21 | removeVideoFromBlacklist, |
21 | reportAbuse, | 22 | reportAbuse, |
22 | unfollow, | 23 | unfollow, |
24 | updateAbuse, | ||
23 | updateCustomConfig, | 25 | updateCustomConfig, |
24 | updateCustomSubConfig, | 26 | updateCustomSubConfig, |
25 | wait, | 27 | wait |
26 | updateAbuse, | ||
27 | addAbuseMessage | ||
28 | } from '../../../../shared/extra-utils' | 28 | } from '../../../../shared/extra-utils' |
29 | import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index' | 29 | import { ServerInfo, uploadVideo } from '../../../../shared/extra-utils/index' |
30 | import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' | 30 | import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' |
31 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' | 31 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' |
32 | import { | 32 | import { |
33 | checkAbuseStateChange, | ||
33 | checkAutoInstanceFollowing, | 34 | checkAutoInstanceFollowing, |
34 | CheckerBaseParams, | 35 | CheckerBaseParams, |
36 | checkNewAbuseMessage, | ||
35 | checkNewAccountAbuseForModerators, | 37 | checkNewAccountAbuseForModerators, |
36 | checkNewBlacklistOnMyVideo, | 38 | checkNewBlacklistOnMyVideo, |
37 | checkNewCommentAbuseForModerators, | 39 | checkNewCommentAbuseForModerators, |
@@ -41,15 +43,12 @@ import { | |||
41 | checkUserRegistered, | 43 | checkUserRegistered, |
42 | checkVideoAutoBlacklistForModerators, | 44 | checkVideoAutoBlacklistForModerators, |
43 | checkVideoIsPublished, | 45 | checkVideoIsPublished, |
44 | prepareNotificationsTest, | 46 | prepareNotificationsTest |
45 | checkAbuseStateChange, | ||
46 | checkNewAbuseMessage | ||
47 | } from '../../../../shared/extra-utils/users/user-notifications' | 47 | } from '../../../../shared/extra-utils/users/user-notifications' |
48 | import { addUserSubscription, removeUserSubscription } from '../../../../shared/extra-utils/users/user-subscriptions' | 48 | import { addUserSubscription, removeUserSubscription } from '../../../../shared/extra-utils/users/user-subscriptions' |
49 | import { CustomConfig } from '../../../../shared/models/server' | 49 | import { CustomConfig } from '../../../../shared/models/server' |
50 | import { UserNotification } from '../../../../shared/models/users' | 50 | import { UserNotification } from '../../../../shared/models/users' |
51 | import { VideoPrivacy } from '../../../../shared/models/videos' | 51 | import { VideoPrivacy } from '../../../../shared/models/videos' |
52 | import { AbuseState } from '@shared/models' | ||
53 | 52 | ||
54 | describe('Test moderation notifications', function () { | 53 | describe('Test moderation notifications', function () { |
55 | let servers: ServerInfo[] = [] | 54 | let servers: ServerInfo[] = [] |
@@ -364,16 +363,7 @@ describe('Test moderation notifications', function () { | |||
364 | 363 | ||
365 | describe('New instance follows', function () { | 364 | describe('New instance follows', function () { |
366 | const instanceIndexServer = new MockInstancesIndex() | 365 | const instanceIndexServer = new MockInstancesIndex() |
367 | const config = { | 366 | let config: any |
368 | followings: { | ||
369 | instance: { | ||
370 | autoFollowIndex: { | ||
371 | indexUrl: 'http://localhost:42101/api/v1/instances/hosts', | ||
372 | enabled: true | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | let baseParams: CheckerBaseParams | 367 | let baseParams: CheckerBaseParams |
378 | 368 | ||
379 | before(async () => { | 369 | before(async () => { |
@@ -384,8 +374,19 @@ describe('Test moderation notifications', function () { | |||
384 | token: servers[0].accessToken | 374 | token: servers[0].accessToken |
385 | } | 375 | } |
386 | 376 | ||
387 | await instanceIndexServer.initialize() | 377 | const port = await instanceIndexServer.initialize() |
388 | instanceIndexServer.addInstance(servers[1].host) | 378 | instanceIndexServer.addInstance(servers[1].host) |
379 | |||
380 | config = { | ||
381 | followings: { | ||
382 | instance: { | ||
383 | autoFollowIndex: { | ||
384 | indexUrl: `http://localhost:${port}/api/v1/instances/hosts`, | ||
385 | enabled: true | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | } | ||
389 | }) | 390 | }) |
390 | 391 | ||
391 | it('Should send a notification only to admin when there is a new instance follower', async function () { | 392 | it('Should send a notification only to admin when there is a new instance follower', async function () { |
diff --git a/server/tests/api/server/auto-follows.ts b/server/tests/api/server/auto-follows.ts index e04d70af4..1519b263f 100644 --- a/server/tests/api/server/auto-follows.ts +++ b/server/tests/api/server/auto-follows.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 | ||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | ||
5 | import { | 5 | import { |
6 | acceptFollower, | 6 | acceptFollower, |
7 | cleanupTests, | 7 | cleanupTests, |
@@ -153,9 +153,10 @@ describe('Test auto follows', function () { | |||
153 | 153 | ||
154 | describe('Auto follow index', function () { | 154 | describe('Auto follow index', function () { |
155 | const instanceIndexServer = new MockInstancesIndex() | 155 | const instanceIndexServer = new MockInstancesIndex() |
156 | let port: number | ||
156 | 157 | ||
157 | before(async () => { | 158 | before(async () => { |
158 | await instanceIndexServer.initialize() | 159 | port = await instanceIndexServer.initialize() |
159 | }) | 160 | }) |
160 | 161 | ||
161 | it('Should not auto follow index if the option is not enabled', async function () { | 162 | it('Should not auto follow index if the option is not enabled', async function () { |
@@ -177,7 +178,7 @@ describe('Test auto follows', function () { | |||
177 | followings: { | 178 | followings: { |
178 | instance: { | 179 | instance: { |
179 | autoFollowIndex: { | 180 | autoFollowIndex: { |
180 | indexUrl: 'http://localhost:42101/api/v1/instances/hosts', | 181 | indexUrl: `http://localhost:${port}/api/v1/instances/hosts`, |
181 | enabled: true | 182 | enabled: true |
182 | } | 183 | } |
183 | } | 184 | } |
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index 0b0f48d22..1d9ea31df 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -12,6 +12,7 @@ import { | |||
12 | getConfig, | 12 | getConfig, |
13 | getCustomConfig, | 13 | getCustomConfig, |
14 | killallServers, | 14 | killallServers, |
15 | makeGetRequest, | ||
15 | parallelTests, | 16 | parallelTests, |
16 | registerUser, | 17 | registerUser, |
17 | reRunServer, | 18 | reRunServer, |
@@ -508,6 +509,39 @@ describe('Test config', function () { | |||
508 | checkInitialConfig(server, data) | 509 | checkInitialConfig(server, data) |
509 | }) | 510 | }) |
510 | 511 | ||
512 | it('Should enable frameguard', async function () { | ||
513 | this.timeout(25000) | ||
514 | |||
515 | { | ||
516 | const res = await makeGetRequest({ | ||
517 | url: server.url, | ||
518 | path: '/api/v1/config', | ||
519 | statusCodeExpected: 200 | ||
520 | }) | ||
521 | |||
522 | expect(res.headers['x-frame-options']).to.exist | ||
523 | } | ||
524 | |||
525 | killallServers([ server ]) | ||
526 | |||
527 | const config = { | ||
528 | security: { | ||
529 | frameguard: { enabled: false } | ||
530 | } | ||
531 | } | ||
532 | server = await reRunServer(server, config) | ||
533 | |||
534 | { | ||
535 | const res = await makeGetRequest({ | ||
536 | url: server.url, | ||
537 | path: '/api/v1/config', | ||
538 | statusCodeExpected: 200 | ||
539 | }) | ||
540 | |||
541 | expect(res.headers['x-frame-options']).to.not.exist | ||
542 | } | ||
543 | }) | ||
544 | |||
511 | after(async function () { | 545 | after(async function () { |
512 | await cleanupTests([ server ]) | 546 | await cleanupTests([ server ]) |
513 | }) | 547 | }) |
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/server/services.ts b/server/tests/api/server/services.ts index df910c111..f0fa91674 100644 --- a/server/tests/api/server/services.ts +++ b/server/tests/api/server/services.ts | |||
@@ -20,6 +20,7 @@ const expect = chai.expect | |||
20 | describe('Test services', function () { | 20 | describe('Test services', function () { |
21 | let server: ServerInfo = null | 21 | let server: ServerInfo = null |
22 | let playlistUUID: string | 22 | let playlistUUID: string |
23 | let playlistDisplayName: string | ||
23 | let video: Video | 24 | let video: Video |
24 | 25 | ||
25 | before(async function () { | 26 | before(async function () { |
@@ -52,6 +53,7 @@ describe('Test services', function () { | |||
52 | }) | 53 | }) |
53 | 54 | ||
54 | playlistUUID = res.body.videoPlaylist.uuid | 55 | playlistUUID = res.body.videoPlaylist.uuid |
56 | playlistDisplayName = 'The Life and Times of Scrooge McDuck' | ||
55 | 57 | ||
56 | await addVideoInPlaylist({ | 58 | await addVideoInPlaylist({ |
57 | url: server.url, | 59 | url: server.url, |
@@ -69,7 +71,7 @@ describe('Test services', function () { | |||
69 | 71 | ||
70 | const res = await getOEmbed(server.url, oembedUrl) | 72 | const res = await getOEmbed(server.url, oembedUrl) |
71 | const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + | 73 | const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + |
72 | `src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + | 74 | `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + |
73 | 'frameborder="0" allowfullscreen></iframe>' | 75 | 'frameborder="0" allowfullscreen></iframe>' |
74 | const expectedThumbnailUrl = 'http://localhost:' + server.port + video.previewPath | 76 | const expectedThumbnailUrl = 'http://localhost:' + server.port + video.previewPath |
75 | 77 | ||
@@ -88,7 +90,7 @@ describe('Test services', function () { | |||
88 | 90 | ||
89 | const res = await getOEmbed(server.url, oembedUrl) | 91 | const res = await getOEmbed(server.url, oembedUrl) |
90 | const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + | 92 | const expectedHtml = '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts" ' + |
91 | `src="http://localhost:${server.port}/video-playlists/embed/${playlistUUID}" ` + | 93 | `title="${playlistDisplayName}" src="http://localhost:${server.port}/video-playlists/embed/${playlistUUID}" ` + |
92 | 'frameborder="0" allowfullscreen></iframe>' | 94 | 'frameborder="0" allowfullscreen></iframe>' |
93 | 95 | ||
94 | expect(res.body.html).to.equal(expectedHtml) | 96 | expect(res.body.html).to.equal(expectedHtml) |
@@ -97,8 +99,8 @@ describe('Test services', function () { | |||
97 | expect(res.body.width).to.equal(560) | 99 | expect(res.body.width).to.equal(560) |
98 | expect(res.body.height).to.equal(315) | 100 | expect(res.body.height).to.equal(315) |
99 | expect(res.body.thumbnail_url).exist | 101 | expect(res.body.thumbnail_url).exist |
100 | expect(res.body.thumbnail_width).to.equal(223) | 102 | expect(res.body.thumbnail_width).to.equal(280) |
101 | expect(res.body.thumbnail_height).to.equal(122) | 103 | expect(res.body.thumbnail_height).to.equal(157) |
102 | }) | 104 | }) |
103 | 105 | ||
104 | it('Should have a valid oEmbed response with small max height query', async function () { | 106 | it('Should have a valid oEmbed response with small max height query', async function () { |
@@ -109,7 +111,7 @@ describe('Test services', function () { | |||
109 | 111 | ||
110 | const res = await getOEmbed(server.url, oembedUrl, format, maxHeight, maxWidth) | 112 | const res = await getOEmbed(server.url, oembedUrl, format, maxHeight, maxWidth) |
111 | const expectedHtml = '<iframe width="50" height="50" sandbox="allow-same-origin allow-scripts" ' + | 113 | const expectedHtml = '<iframe width="50" height="50" sandbox="allow-same-origin allow-scripts" ' + |
112 | `src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + | 114 | `title="${video.name}" src="http://localhost:${server.port}/videos/embed/${video.uuid}" ` + |
113 | 'frameborder="0" allowfullscreen></iframe>' | 115 | 'frameborder="0" allowfullscreen></iframe>' |
114 | 116 | ||
115 | expect(res.body.html).to.equal(expectedHtml) | 117 | expect(res.body.html).to.equal(expectedHtml) |
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts index eb474c1f5..304181a6d 100644 --- a/server/tests/api/server/stats.ts +++ b/server/tests/api/server/stats.ts | |||
@@ -3,8 +3,10 @@ | |||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { | 5 | import { |
6 | addVideoChannel, | ||
6 | cleanupTests, | 7 | cleanupTests, |
7 | createUser, | 8 | createUser, |
9 | createVideoPlaylist, | ||
8 | doubleFollow, | 10 | doubleFollow, |
9 | flushAndRunMultipleServers, | 11 | flushAndRunMultipleServers, |
10 | follow, | 12 | follow, |
@@ -21,12 +23,14 @@ import { waitJobs } from '../../../../shared/extra-utils/server/jobs' | |||
21 | import { getStats } from '../../../../shared/extra-utils/server/stats' | 23 | import { getStats } from '../../../../shared/extra-utils/server/stats' |
22 | import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' | 24 | import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' |
23 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' | 25 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' |
26 | import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' | ||
24 | import { ActivityType } from '@shared/models' | 27 | import { ActivityType } from '@shared/models' |
25 | 28 | ||
26 | const expect = chai.expect | 29 | const expect = chai.expect |
27 | 30 | ||
28 | describe('Test stats (excluding redundancy)', function () { | 31 | describe('Test stats (excluding redundancy)', function () { |
29 | let servers: ServerInfo[] = [] | 32 | let servers: ServerInfo[] = [] |
33 | let channelId | ||
30 | const user = { | 34 | const user = { |
31 | username: 'user1', | 35 | username: 'user1', |
32 | password: 'super_password' | 36 | password: 'super_password' |
@@ -70,6 +74,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
70 | expect(data.totalVideos).to.equal(1) | 74 | expect(data.totalVideos).to.equal(1) |
71 | expect(data.totalInstanceFollowers).to.equal(2) | 75 | expect(data.totalInstanceFollowers).to.equal(2) |
72 | expect(data.totalInstanceFollowing).to.equal(1) | 76 | expect(data.totalInstanceFollowing).to.equal(1) |
77 | expect(data.totalLocalPlaylists).to.equal(0) | ||
73 | }) | 78 | }) |
74 | 79 | ||
75 | it('Should have the correct stats on instance 2', async function () { | 80 | it('Should have the correct stats on instance 2', async function () { |
@@ -85,6 +90,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
85 | expect(data.totalVideos).to.equal(1) | 90 | expect(data.totalVideos).to.equal(1) |
86 | expect(data.totalInstanceFollowers).to.equal(1) | 91 | expect(data.totalInstanceFollowers).to.equal(1) |
87 | expect(data.totalInstanceFollowing).to.equal(1) | 92 | expect(data.totalInstanceFollowing).to.equal(1) |
93 | expect(data.totalLocalPlaylists).to.equal(0) | ||
88 | }) | 94 | }) |
89 | 95 | ||
90 | it('Should have the correct stats on instance 3', async function () { | 96 | it('Should have the correct stats on instance 3', async function () { |
@@ -99,6 +105,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
99 | expect(data.totalVideos).to.equal(1) | 105 | expect(data.totalVideos).to.equal(1) |
100 | expect(data.totalInstanceFollowing).to.equal(1) | 106 | expect(data.totalInstanceFollowing).to.equal(1) |
101 | expect(data.totalInstanceFollowers).to.equal(0) | 107 | expect(data.totalInstanceFollowers).to.equal(0) |
108 | expect(data.totalLocalPlaylists).to.equal(0) | ||
102 | }) | 109 | }) |
103 | 110 | ||
104 | it('Should have the correct total videos stats after an unfollow', async function () { | 111 | it('Should have the correct total videos stats after an unfollow', async function () { |
@@ -113,7 +120,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
113 | expect(data.totalVideos).to.equal(0) | 120 | expect(data.totalVideos).to.equal(0) |
114 | }) | 121 | }) |
115 | 122 | ||
116 | it('Should have the correct active users stats', async function () { | 123 | it('Should have the correct active user stats', async function () { |
117 | const server = servers[0] | 124 | const server = servers[0] |
118 | 125 | ||
119 | { | 126 | { |
@@ -135,6 +142,69 @@ describe('Test stats (excluding redundancy)', function () { | |||
135 | } | 142 | } |
136 | }) | 143 | }) |
137 | 144 | ||
145 | it('Should have the correct active channel stats', async function () { | ||
146 | const server = servers[0] | ||
147 | |||
148 | { | ||
149 | const res = await getStats(server.url) | ||
150 | const data: ServerStats = res.body | ||
151 | expect(data.totalLocalDailyActiveVideoChannels).to.equal(1) | ||
152 | expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1) | ||
153 | expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1) | ||
154 | } | ||
155 | |||
156 | { | ||
157 | const channelAttributes = { | ||
158 | name: 'stats_channel', | ||
159 | displayName: 'My stats channel' | ||
160 | } | ||
161 | const resChannel = await addVideoChannel(server.url, server.accessToken, channelAttributes) | ||
162 | channelId = resChannel.body.videoChannel.id | ||
163 | |||
164 | const res = await getStats(server.url) | ||
165 | const data: ServerStats = res.body | ||
166 | expect(data.totalLocalDailyActiveVideoChannels).to.equal(1) | ||
167 | expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1) | ||
168 | expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1) | ||
169 | } | ||
170 | |||
171 | { | ||
172 | await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.webm', channelId }) | ||
173 | |||
174 | const res = await getStats(server.url) | ||
175 | const data: ServerStats = res.body | ||
176 | expect(data.totalLocalDailyActiveVideoChannels).to.equal(2) | ||
177 | expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(2) | ||
178 | expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(2) | ||
179 | } | ||
180 | }) | ||
181 | |||
182 | it('Should have the correct playlist stats', async function () { | ||
183 | const server = servers[0] | ||
184 | |||
185 | { | ||
186 | const resStats = await getStats(server.url) | ||
187 | const dataStats: ServerStats = resStats.body | ||
188 | expect(dataStats.totalLocalPlaylists).to.equal(0) | ||
189 | } | ||
190 | |||
191 | { | ||
192 | await createVideoPlaylist({ | ||
193 | url: server.url, | ||
194 | token: server.accessToken, | ||
195 | playlistAttrs: { | ||
196 | displayName: 'playlist for count', | ||
197 | privacy: VideoPlaylistPrivacy.PUBLIC, | ||
198 | videoChannelId: channelId | ||
199 | } | ||
200 | }) | ||
201 | |||
202 | const resStats = await getStats(server.url) | ||
203 | const dataStats: ServerStats = resStats.body | ||
204 | expect(dataStats.totalLocalPlaylists).to.equal(1) | ||
205 | } | ||
206 | }) | ||
207 | |||
138 | it('Should correctly count video file sizes if transcoding is enabled', async function () { | 208 | it('Should correctly count video file sizes if transcoding is enabled', async function () { |
139 | this.timeout(60000) | 209 | this.timeout(60000) |
140 | 210 | ||
@@ -173,8 +243,8 @@ describe('Test stats (excluding redundancy)', function () { | |||
173 | { | 243 | { |
174 | const res = await getStats(servers[0].url) | 244 | const res = await getStats(servers[0].url) |
175 | const data: ServerStats = res.body | 245 | const data: ServerStats = res.body |
176 | expect(data.totalLocalVideoFilesSize).to.be.greaterThan(300000) | 246 | expect(data.totalLocalVideoFilesSize).to.be.greaterThan(500000) |
177 | expect(data.totalLocalVideoFilesSize).to.be.lessThan(400000) | 247 | expect(data.totalLocalVideoFilesSize).to.be.lessThan(600000) |
178 | } | 248 | } |
179 | }) | 249 | }) |
180 | 250 | ||
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' | |||
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { AbuseState, AbuseUpdate, MyUser, User, UserRole, Video, VideoPlaylistType } from '@shared/models' | 5 | import { AbuseState, AbuseUpdate, MyUser, User, UserRole, Video, VideoPlaylistType } from '@shared/models' |
6 | import { CustomConfig } from '@shared/models/server' | 6 | import { CustomConfig } from '@shared/models/server' |
7 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | ||
7 | import { | 8 | import { |
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' |
46 | import { follow } from '../../../../shared/extra-utils/server/follows' | 51 | import { follow } from '../../../../shared/extra-utils/server/follows' |
47 | import { logout, serverLogin, setAccessTokensToServers } from '../../../../shared/extra-utils/users/login' | 52 | import { logout, refreshToken, setAccessTokensToServers } from '../../../../shared/extra-utils/users/login' |
48 | import { getMyVideos } from '../../../../shared/extra-utils/videos/videos' | 53 | import { getMyVideos } from '../../../../shared/extra-utils/videos/videos' |
49 | import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' | 54 | import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' |
50 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | ||
51 | 55 | ||
52 | const expect = chai.expect | 56 | const 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/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 367f99fdd..d12d58e75 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -2,16 +2,20 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { basename } from 'path' | ||
5 | import { | 6 | import { |
6 | cleanupTests, | 7 | cleanupTests, |
7 | createUser, | 8 | createUser, |
9 | deleteVideoChannelImage, | ||
8 | doubleFollow, | 10 | doubleFollow, |
9 | flushAndRunMultipleServers, | 11 | flushAndRunMultipleServers, |
12 | getActorImage, | ||
10 | getVideo, | 13 | getVideo, |
14 | getVideoChannel, | ||
11 | getVideoChannelVideos, | 15 | getVideoChannelVideos, |
12 | testImage, | 16 | testImage, |
13 | updateVideo, | 17 | updateVideo, |
14 | updateVideoChannelAvatar, | 18 | updateVideoChannelImage, |
15 | uploadVideo, | 19 | uploadVideo, |
16 | userLogin, | 20 | userLogin, |
17 | wait | 21 | wait |
@@ -21,7 +25,6 @@ import { | |||
21 | deleteVideoChannel, | 25 | deleteVideoChannel, |
22 | getAccountVideoChannelsList, | 26 | getAccountVideoChannelsList, |
23 | getMyUserInformation, | 27 | getMyUserInformation, |
24 | getVideoChannel, | ||
25 | getVideoChannelsList, | 28 | getVideoChannelsList, |
26 | ServerInfo, | 29 | ServerInfo, |
27 | setAccessTokensToServers, | 30 | setAccessTokensToServers, |
@@ -30,9 +33,17 @@ import { | |||
30 | } from '../../../../shared/extra-utils/index' | 33 | } from '../../../../shared/extra-utils/index' |
31 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' | 34 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' |
32 | import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/index' | 35 | import { User, Video, VideoChannel, VideoDetails } from '../../../../shared/index' |
36 | import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants' | ||
33 | 37 | ||
34 | const expect = chai.expect | 38 | const expect = chai.expect |
35 | 39 | ||
40 | async function findChannel (server: ServerInfo, channelId: number) { | ||
41 | const res = await getVideoChannelsList(server.url, 0, 5, '-name') | ||
42 | const videoChannel = res.body.data.find(c => c.id === channelId) | ||
43 | |||
44 | return videoChannel as VideoChannel | ||
45 | } | ||
46 | |||
36 | describe('Test video channels', function () { | 47 | describe('Test video channels', function () { |
37 | let servers: ServerInfo[] | 48 | let servers: ServerInfo[] |
38 | let userInfo: User | 49 | let userInfo: User |
@@ -262,38 +273,94 @@ describe('Test video channels', function () { | |||
262 | }) | 273 | }) |
263 | 274 | ||
264 | it('Should update video channel avatar', async function () { | 275 | it('Should update video channel avatar', async function () { |
265 | this.timeout(5000) | 276 | this.timeout(15000) |
266 | 277 | ||
267 | const fixture = 'avatar.png' | 278 | const fixture = 'avatar.png' |
268 | 279 | ||
269 | await updateVideoChannelAvatar({ | 280 | await updateVideoChannelImage({ |
270 | url: servers[0].url, | 281 | url: servers[0].url, |
271 | accessToken: servers[0].accessToken, | 282 | accessToken: servers[0].accessToken, |
272 | videoChannelName: 'second_video_channel', | 283 | videoChannelName: 'second_video_channel', |
273 | fixture | 284 | fixture, |
285 | type: 'avatar' | ||
274 | }) | 286 | }) |
275 | 287 | ||
276 | await waitJobs(servers) | 288 | await waitJobs(servers) |
289 | |||
290 | for (const server of servers) { | ||
291 | const videoChannel = await findChannel(server, secondVideoChannelId) | ||
292 | |||
293 | await testImage(server.url, 'avatar-resized', videoChannel.avatar.path, '.png') | ||
294 | |||
295 | const row = await getActorImage(server.internalServerNumber, basename(videoChannel.avatar.path)) | ||
296 | expect(row.height).to.equal(ACTOR_IMAGES_SIZE.AVATARS.height) | ||
297 | expect(row.width).to.equal(ACTOR_IMAGES_SIZE.AVATARS.width) | ||
298 | } | ||
277 | }) | 299 | }) |
278 | 300 | ||
279 | it('Should have video channel avatar updated', async function () { | 301 | it('Should update video channel banner', async function () { |
302 | this.timeout(15000) | ||
303 | |||
304 | const fixture = 'banner.jpg' | ||
305 | |||
306 | await updateVideoChannelImage({ | ||
307 | url: servers[0].url, | ||
308 | accessToken: servers[0].accessToken, | ||
309 | videoChannelName: 'second_video_channel', | ||
310 | fixture, | ||
311 | type: 'banner' | ||
312 | }) | ||
313 | |||
314 | await waitJobs(servers) | ||
315 | |||
280 | for (const server of servers) { | 316 | for (const server of servers) { |
281 | const res = await getVideoChannelsList(server.url, 0, 1, '-name') | 317 | const res = await getVideoChannel(server.url, 'second_video_channel@' + servers[0].host) |
318 | const videoChannel = res.body | ||
282 | 319 | ||
283 | const videoChannel = res.body.data.find(c => c.id === secondVideoChannelId) | 320 | await testImage(server.url, 'banner-resized', videoChannel.banner.path) |
284 | 321 | ||
285 | await testImage(server.url, 'avatar-resized', videoChannel.avatar.path, '.png') | 322 | const row = await getActorImage(server.internalServerNumber, basename(videoChannel.banner.path)) |
323 | expect(row.height).to.equal(ACTOR_IMAGES_SIZE.BANNERS.height) | ||
324 | expect(row.width).to.equal(ACTOR_IMAGES_SIZE.BANNERS.width) | ||
325 | } | ||
326 | }) | ||
327 | |||
328 | it('Should delete the video channel avatar', async function () { | ||
329 | this.timeout(15000) | ||
330 | |||
331 | await deleteVideoChannelImage({ | ||
332 | url: servers[0].url, | ||
333 | accessToken: servers[0].accessToken, | ||
334 | videoChannelName: 'second_video_channel', | ||
335 | type: 'avatar' | ||
336 | }) | ||
337 | |||
338 | await waitJobs(servers) | ||
339 | |||
340 | for (const server of servers) { | ||
341 | const videoChannel = await findChannel(server, secondVideoChannelId) | ||
342 | |||
343 | expect(videoChannel.avatar).to.be.null | ||
286 | } | 344 | } |
287 | }) | 345 | }) |
288 | 346 | ||
289 | it('Should get video channel', async function () { | 347 | it('Should delete the video channel banner', async function () { |
290 | const res = await getVideoChannel(servers[0].url, 'second_video_channel') | 348 | this.timeout(15000) |
349 | |||
350 | await deleteVideoChannelImage({ | ||
351 | url: servers[0].url, | ||
352 | accessToken: servers[0].accessToken, | ||
353 | videoChannelName: 'second_video_channel', | ||
354 | type: 'banner' | ||
355 | }) | ||
356 | |||
357 | await waitJobs(servers) | ||
358 | |||
359 | for (const server of servers) { | ||
360 | const videoChannel = await findChannel(server, secondVideoChannelId) | ||
291 | 361 | ||
292 | const videoChannel = res.body | 362 | expect(videoChannel.banner).to.be.null |
293 | expect(videoChannel.name).to.equal('second_video_channel') | 363 | } |
294 | expect(videoChannel.displayName).to.equal('video channel updated') | ||
295 | expect(videoChannel.description).to.equal('video channel description updated') | ||
296 | expect(videoChannel.support).to.equal('video channel support text updated') | ||
297 | }) | 364 | }) |
298 | 365 | ||
299 | it('Should list the second video channel videos', async function () { | 366 | it('Should list the second video channel videos', async function () { |
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' | |||
6 | import './plugins' | 6 | import './plugins' |
7 | import './print-transcode-command' | 7 | import './print-transcode-command' |
8 | import './prune-storage' | 8 | import './prune-storage' |
9 | import './regenerate-thumbnails' | ||
9 | import './reset-password' | 10 | import './reset-password' |
10 | import './update-host' | 11 | import './update-host' |
diff --git a/server/tests/cli/print-transcode-command.ts b/server/tests/cli/print-transcode-command.ts index 4a7988d4d..2d7255db7 100644 --- a/server/tests/cli/print-transcode-command.ts +++ b/server/tests/cli/print-transcode-command.ts | |||
@@ -22,7 +22,8 @@ describe('Test create transcoding jobs', function () { | |||
22 | const command = await execCLI(`npm run print-transcode-command -- ${fixturePath} -r ${resolution}`) | 22 | const command = await execCLI(`npm run print-transcode-command -- ${fixturePath} -r ${resolution}`) |
23 | const targetBitrate = Math.min(getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS), bitrate) | 23 | const targetBitrate = Math.min(getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS), bitrate) |
24 | 24 | ||
25 | expect(command).to.includes(`-y -acodec aac -vcodec libx264 -filter:v scale=w=trunc(oh*a/2)*2:h=${resolution}`) | 25 | expect(command).to.includes(`-vf scale=w=-2:h=${resolution}`) |
26 | expect(command).to.includes(`-y -acodec aac -vcodec libx264`) | ||
26 | expect(command).to.includes('-f mp4') | 27 | expect(command).to.includes('-f mp4') |
27 | expect(command).to.includes('-movflags faststart') | 28 | expect(command).to.includes('-movflags faststart') |
28 | expect(command).to.includes('-b:a 256k') | 29 | expect(command).to.includes('-b:a 256k') |
diff --git a/server/tests/cli/regenerate-thumbnails.ts b/server/tests/cli/regenerate-thumbnails.ts new file mode 100644 index 000000000..8acb9f263 --- /dev/null +++ b/server/tests/cli/regenerate-thumbnails.ts | |||
@@ -0,0 +1,124 @@ | |||
1 | import 'mocha' | ||
2 | import { expect } from 'chai' | ||
3 | import { writeFile } from 'fs-extra' | ||
4 | import { basename, join } from 'path' | ||
5 | import { Video, VideoDetails } from '@shared/models' | ||
6 | import { | ||
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' | ||
20 | import { HttpStatusCode } from '@shared/core-utils' | ||
21 | |||
22 | async function testThumbnail (server: ServerInfo, videoId: number | string) { | ||
23 | const res = await getVideo(server.url, videoId) | ||
24 | const video: VideoDetails = res.body | ||
25 | |||
26 | const res1 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200) | ||
27 | expect(res1.body).to.not.have.lengthOf(0) | ||
28 | |||
29 | const res2 = await makeRawRequest(join(server.url, video.thumbnailPath), HttpStatusCode.OK_200) | ||
30 | expect(res2.body).to.not.have.lengthOf(0) | ||
31 | } | ||
32 | |||
33 | describe('Test regenerate thumbnails script', function () { | ||
34 | let servers: ServerInfo[] | ||
35 | |||
36 | let video1: Video | ||
37 | let video2: Video | ||
38 | let remoteVideo: Video | ||
39 | |||
40 | let thumbnail1Path: string | ||
41 | let thumbnailRemotePath: string | ||
42 | |||
43 | before(async function () { | ||
44 | this.timeout(60000) | ||
45 | |||
46 | servers = await flushAndRunMultipleServers(2) | ||
47 | await setAccessTokensToServers(servers) | ||
48 | |||
49 | await doubleFollow(servers[0], servers[1]) | ||
50 | |||
51 | { | ||
52 | const videoUUID1 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 1' })).uuid | ||
53 | video1 = await (getVideo(servers[0].url, videoUUID1).then(res => res.body)) | ||
54 | |||
55 | thumbnail1Path = join(buildServerDirectory(servers[0], 'thumbnails'), basename(video1.thumbnailPath)) | ||
56 | |||
57 | const videoUUID2 = (await uploadVideoAndGetId({ server: servers[0], videoName: 'video 2' })).uuid | ||
58 | video2 = await (getVideo(servers[0].url, videoUUID2).then(res => res.body)) | ||
59 | } | ||
60 | |||
61 | { | ||
62 | const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'video 3' })).uuid | ||
63 | await waitJobs(servers) | ||
64 | |||
65 | remoteVideo = await (getVideo(servers[0].url, videoUUID).then(res => res.body)) | ||
66 | |||
67 | thumbnailRemotePath = join(buildServerDirectory(servers[0], 'thumbnails'), basename(remoteVideo.thumbnailPath)) | ||
68 | } | ||
69 | |||
70 | await writeFile(thumbnail1Path, '') | ||
71 | await writeFile(thumbnailRemotePath, '') | ||
72 | }) | ||
73 | |||
74 | it('Should have empty thumbnails', async function () { | ||
75 | { | ||
76 | const res = await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.OK_200) | ||
77 | expect(res.body).to.have.lengthOf(0) | ||
78 | } | ||
79 | |||
80 | { | ||
81 | const res = await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.OK_200) | ||
82 | expect(res.body).to.not.have.lengthOf(0) | ||
83 | } | ||
84 | |||
85 | { | ||
86 | const res = await makeRawRequest(join(servers[0].url, remoteVideo.thumbnailPath), HttpStatusCode.OK_200) | ||
87 | expect(res.body).to.have.lengthOf(0) | ||
88 | } | ||
89 | }) | ||
90 | |||
91 | it('Should regenerate local thumbnails from the CLI', async function () { | ||
92 | this.timeout(15000) | ||
93 | |||
94 | const env = getEnvCli(servers[0]) | ||
95 | await execCLI(`${env} npm run regenerate-thumbnails`) | ||
96 | }) | ||
97 | |||
98 | it('Should have generated new thumbnail files', async function () { | ||
99 | await testThumbnail(servers[0], video1.uuid) | ||
100 | await testThumbnail(servers[0], video2.uuid) | ||
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 | it('Should have deleted old thumbnail files', async function () { | ||
107 | { | ||
108 | await makeRawRequest(join(servers[0].url, video1.thumbnailPath), HttpStatusCode.NOT_FOUND_404) | ||
109 | } | ||
110 | |||
111 | { | ||
112 | await makeRawRequest(join(servers[0].url, video2.thumbnailPath), HttpStatusCode.NOT_FOUND_404) | ||
113 | } | ||
114 | |||
115 | { | ||
116 | const res = await makeRawRequest(join(servers[0].url, remoteVideo.thumbnailPath), HttpStatusCode.OK_200) | ||
117 | expect(res.body).to.have.lengthOf(0) | ||
118 | } | ||
119 | }) | ||
120 | |||
121 | after(async function () { | ||
122 | await cleanupTests(servers) | ||
123 | }) | ||
124 | }) | ||
diff --git a/server/tests/client.ts b/server/tests/client.ts index d608764ee..3c99bcd1f 100644 --- a/server/tests/client.ts +++ b/server/tests/client.ts | |||
@@ -39,7 +39,8 @@ describe('Test a client controllers', function () { | |||
39 | let account: Account | 39 | let account: Account |
40 | 40 | ||
41 | const videoName = 'my super name for server 1' | 41 | const videoName = 'my super name for server 1' |
42 | const videoDescription = 'my super description for server 1' | 42 | const videoDescription = 'my<br> super __description__ for *server* 1<p></p>' |
43 | const videoDescriptionPlainText = 'my super description for server 1' | ||
43 | 44 | ||
44 | const playlistName = 'super playlist name' | 45 | const playlistName = 'super playlist name' |
45 | const playlistDescription = 'super playlist description' | 46 | const playlistDescription = 'super playlist description' |
@@ -169,7 +170,7 @@ describe('Test a client controllers', function () { | |||
169 | .expect(HttpStatusCode.OK_200) | 170 | .expect(HttpStatusCode.OK_200) |
170 | 171 | ||
171 | expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) | 172 | expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) |
172 | expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`) | 173 | expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`) |
173 | expect(res.text).to.contain('<meta property="og:type" content="video" />') | 174 | expect(res.text).to.contain('<meta property="og:type" content="video" />') |
174 | expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) | 175 | expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/videos/watch/${servers[0].video.uuid}" />`) |
175 | }) | 176 | }) |
@@ -181,7 +182,7 @@ describe('Test a client controllers', function () { | |||
181 | .expect(HttpStatusCode.OK_200) | 182 | .expect(HttpStatusCode.OK_200) |
182 | 183 | ||
183 | expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) | 184 | expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`) |
184 | expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`) | 185 | expect(res.text).to.contain(`<meta property="og:description" content="${videoDescriptionPlainText}" />`) |
185 | expect(res.text).to.contain('<meta property="og:type" content="video" />') | 186 | expect(res.text).to.contain('<meta property="og:type" content="video" />') |
186 | expect(res.text).to.contain(`<meta property="og:url" content="${servers[0].url}/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}" />`) |
187 | }) | 188 | }) |
@@ -210,7 +211,7 @@ describe('Test a client controllers', function () { | |||
210 | expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />') | 211 | expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />') |
211 | expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') | 212 | expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />') |
212 | expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`) | 213 | expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`) |
213 | expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescription}" />`) | 214 | expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescriptionPlainText}" />`) |
214 | }) | 215 | }) |
215 | 216 | ||
216 | it('Should have valid twitter card on the watch playlist page', async function () { | 217 | it('Should have valid twitter card on the watch playlist page', async function () { |
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts index f1055ea44..7bad81751 100644 --- a/server/tests/feeds/feeds.ts +++ b/server/tests/feeds/feeds.ts | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import * as libxmljs from 'libxmljs' | 5 | import * as xmlParser from 'fast-xml-parser' |
6 | import { | 6 | import { |
7 | addAccountToAccountBlocklist, | 7 | addAccountToAccountBlocklist, |
8 | addAccountToServerBlocklist, | 8 | addAccountToServerBlocklist, |
@@ -139,12 +139,15 @@ describe('Test syndication feeds', () => { | |||
139 | it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () { | 139 | it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () { |
140 | for (const server of servers) { | 140 | for (const server of servers) { |
141 | const rss = await getXMLfeed(server.url, 'videos') | 141 | const rss = await getXMLfeed(server.url, 'videos') |
142 | const xmlDoc = libxmljs.parseXmlString(rss.text) | 142 | expect(xmlParser.validate(rss.text)).to.be.true |
143 | const xmlEnclosure = xmlDoc.get('/rss/channel/item/enclosure') | 143 | |
144 | expect(xmlEnclosure).to.exist | 144 | const xmlDoc = xmlParser.parse(rss.text, { parseAttributeValue: true, ignoreAttributes: false }) |
145 | expect(xmlEnclosure.attr('type').value()).to.be.equal('application/x-bittorrent') | 145 | |
146 | expect(xmlEnclosure.attr('length').value()).to.be.equal('218910') | 146 | const enclosure = xmlDoc.rss.channel.item[0].enclosure |
147 | expect(xmlEnclosure.attr('url').value()).to.contain('720.torrent') | 147 | expect(enclosure).to.exist |
148 | expect(enclosure['@_type']).to.equal('application/x-bittorrent') | ||
149 | expect(enclosure['@_length']).to.equal(218910) | ||
150 | expect(enclosure['@_url']).to.contain('720.torrent') | ||
148 | } | 151 | } |
149 | }) | 152 | }) |
150 | 153 | ||
diff --git a/server/tests/fixtures/banner-resized.jpg b/server/tests/fixtures/banner-resized.jpg new file mode 100644 index 000000000..13ea422cb --- /dev/null +++ b/server/tests/fixtures/banner-resized.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/banner.jpg b/server/tests/fixtures/banner.jpg new file mode 100644 index 000000000..e5f284f59 --- /dev/null +++ b/server/tests/fixtures/banner.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/peertube-plugin-test-four/main.js b/server/tests/fixtures/peertube-plugin-test-four/main.js index 8df456c8a..ea0599997 100644 --- a/server/tests/fixtures/peertube-plugin-test-four/main.js +++ b/server/tests/fixtures/peertube-plugin-test-four/main.js | |||
@@ -69,7 +69,20 @@ async function register ({ | |||
69 | res.sendStatus(500) | 69 | res.sendStatus(500) |
70 | } | 70 | } |
71 | }) | 71 | }) |
72 | |||
73 | router.get('/server-config', async (req, res) => { | ||
74 | const serverConfig = await peertubeHelpers.config.getServerConfig() | ||
75 | |||
76 | return res.json({ serverConfig }) | ||
77 | }) | ||
78 | |||
79 | router.get('/static-route', async (req, res) => { | ||
80 | const staticRoute = await peertubeHelpers.plugin.getBaseStaticRoute() | ||
81 | |||
82 | return res.json({ staticRoute }) | ||
83 | }) | ||
72 | } | 84 | } |
85 | |||
73 | } | 86 | } |
74 | 87 | ||
75 | async function unregister () { | 88 | async function unregister () { |
diff --git a/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js b/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js index 5990ce1ce..59b136947 100644 --- a/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js +++ b/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js | |||
@@ -1,30 +1,88 @@ | |||
1 | async function register ({ transcodingManager }) { | 1 | async function register ({ transcodingManager }) { |
2 | 2 | ||
3 | // Output options | ||
3 | { | 4 | { |
4 | const builder = () => { | 5 | { |
5 | return { | 6 | const builder = () => { |
6 | outputOptions: [ | 7 | return { |
7 | '-r 10' | 8 | outputOptions: [ |
8 | ] | 9 | '-r 10' |
10 | ] | ||
11 | } | ||
9 | } | 12 | } |
13 | |||
14 | transcodingManager.addVODProfile('libx264', 'low-vod', builder) | ||
10 | } | 15 | } |
11 | 16 | ||
12 | transcodingManager.addVODProfile('libx264', 'low-vod', builder) | 17 | { |
18 | const builder = (options) => { | ||
19 | return { | ||
20 | outputOptions: [ | ||
21 | '-r:' + options.streamNum + ' 5' | ||
22 | ] | ||
23 | } | ||
24 | } | ||
25 | |||
26 | transcodingManager.addLiveProfile('libx264', 'low-live', builder) | ||
27 | } | ||
13 | } | 28 | } |
14 | 29 | ||
30 | // Input options | ||
15 | { | 31 | { |
16 | const builder = (options) => { | 32 | { |
17 | return { | 33 | const builder = () => { |
18 | outputOptions: [ | 34 | return { |
19 | '-r:' + options.streamNum + ' 5' | 35 | inputOptions: [ |
20 | ] | 36 | '-r 5' |
37 | ] | ||
38 | } | ||
21 | } | 39 | } |
40 | |||
41 | transcodingManager.addVODProfile('libx264', 'input-options-vod', builder) | ||
22 | } | 42 | } |
23 | 43 | ||
24 | transcodingManager.addLiveProfile('libx264', 'low-live', builder) | 44 | { |
45 | const builder = () => { | ||
46 | return { | ||
47 | inputOptions: [ | ||
48 | '-r 5' | ||
49 | ] | ||
50 | } | ||
51 | } | ||
52 | |||
53 | transcodingManager.addLiveProfile('libx264', 'input-options-live', builder) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | // Scale filters | ||
58 | { | ||
59 | { | ||
60 | const builder = () => { | ||
61 | return { | ||
62 | scaleFilter: { | ||
63 | name: 'Glomgold' | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | transcodingManager.addVODProfile('libx264', 'bad-scale-vod', builder) | ||
69 | } | ||
70 | |||
71 | { | ||
72 | const builder = () => { | ||
73 | return { | ||
74 | scaleFilter: { | ||
75 | name: 'Flintheart' | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | transcodingManager.addLiveProfile('libx264', 'bad-scale-live', builder) | ||
81 | } | ||
25 | } | 82 | } |
26 | } | 83 | } |
27 | 84 | ||
85 | |||
28 | async function unregister () { | 86 | async function unregister () { |
29 | return | 87 | return |
30 | } | 88 | } |
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/lib.js b/server/tests/fixtures/peertube-plugin-test-unloading/lib.js new file mode 100644 index 000000000..f57e7cb01 --- /dev/null +++ b/server/tests/fixtures/peertube-plugin-test-unloading/lib.js | |||
@@ -0,0 +1,2 @@ | |||
1 | const d = new Date() | ||
2 | exports.value = d.getTime() | ||
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/main.js b/server/tests/fixtures/peertube-plugin-test-unloading/main.js new file mode 100644 index 000000000..5c8457cef --- /dev/null +++ b/server/tests/fixtures/peertube-plugin-test-unloading/main.js | |||
@@ -0,0 +1,14 @@ | |||
1 | const lib = require('./lib') | ||
2 | |||
3 | async function register ({ getRouter }) { | ||
4 | const router = getRouter() | ||
5 | router.get('/get', (req, res) => res.json({ message: lib.value })) | ||
6 | } | ||
7 | |||
8 | async function unregister () { | ||
9 | } | ||
10 | |||
11 | module.exports = { | ||
12 | register, | ||
13 | unregister | ||
14 | } | ||
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/package.json b/server/tests/fixtures/peertube-plugin-test-unloading/package.json new file mode 100644 index 000000000..7076d4b6f --- /dev/null +++ b/server/tests/fixtures/peertube-plugin-test-unloading/package.json | |||
@@ -0,0 +1,20 @@ | |||
1 | { | ||
2 | "name": "peertube-plugin-test-unloading", | ||
3 | "version": "0.0.1", | ||
4 | "description": "Plugin test (modules unloading)", | ||
5 | "engine": { | ||
6 | "peertube": ">=1.3.0" | ||
7 | }, | ||
8 | "keywords": [ | ||
9 | "peertube", | ||
10 | "plugin" | ||
11 | ], | ||
12 | "homepage": "https://github.com/Chocobozzz/PeerTube", | ||
13 | "author": "Chocobozzz", | ||
14 | "bugs": "https://github.com/Chocobozzz/PeerTube/issues", | ||
15 | "library": "./main.js", | ||
16 | "staticDirs": {}, | ||
17 | "css": [], | ||
18 | "clientScripts": [], | ||
19 | "translations": {} | ||
20 | } | ||
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 | ||
189 | async function unregister () { | 259 | async function unregister () { |
diff --git a/server/tests/fixtures/thumbnail-playlist.jpg b/server/tests/fixtures/thumbnail-playlist.jpg index 19db4f18c..62cd77435 100644 --- a/server/tests/fixtures/thumbnail-playlist.jpg +++ b/server/tests/fixtures/thumbnail-playlist.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_import_thumbnail.jpg b/server/tests/fixtures/video_import_thumbnail.jpg index fcc50b75f..9ee1bc382 100644 --- a/server/tests/fixtures/video_import_thumbnail.jpg +++ b/server/tests/fixtures/video_import_thumbnail.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short.mp4.jpg b/server/tests/fixtures/video_short.mp4.jpg index 48790ffec..62cd77435 100644 --- a/server/tests/fixtures/video_short.mp4.jpg +++ b/server/tests/fixtures/video_short.mp4.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short.ogv.jpg b/server/tests/fixtures/video_short.ogv.jpg index c4c1d00e5..62cd77435 100644 --- a/server/tests/fixtures/video_short.ogv.jpg +++ b/server/tests/fixtures/video_short.ogv.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short.webm.jpg b/server/tests/fixtures/video_short.webm.jpg index 7f8047516..62cd77435 100644 --- a/server/tests/fixtures/video_short.webm.jpg +++ b/server/tests/fixtures/video_short.webm.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short1.webm.jpg b/server/tests/fixtures/video_short1.webm.jpg index 582eb9ea3..615cb2a5d 100644 --- a/server/tests/fixtures/video_short1.webm.jpg +++ b/server/tests/fixtures/video_short1.webm.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short2.webm.jpg b/server/tests/fixtures/video_short2.webm.jpg index b331aba3b..aa3126381 100644 --- a/server/tests/fixtures/video_short2.webm.jpg +++ b/server/tests/fixtures/video_short2.webm.jpg | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short3.webm.jpg b/server/tests/fixtures/video_short3.webm.jpg index ec8652167..62cd77435 100644 --- a/server/tests/fixtures/video_short3.webm.jpg +++ b/server/tests/fixtures/video_short3.webm.jpg | |||
Binary files differ | |||
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 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' | ||
5 | import { get4KFileUrl, root, wait } from '../../../shared/extra-utils' | ||
6 | import { join } from 'path' | ||
7 | import { pathExists, remove } from 'fs-extra' | ||
8 | import { expect } from 'chai' | 4 | import { expect } from 'chai' |
5 | import { pathExists, remove } from 'fs-extra' | ||
6 | import { join } from 'path' | ||
7 | import { get4KFileUrl, root, wait } from '../../../shared/extra-utils' | ||
8 | import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' | ||
9 | 9 | ||
10 | describe('Request helpers', function () { | 10 | describe('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 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { advancedVideoChannelSearch } from '@shared/extra-utils/search/video-channels' | ||
5 | import { ServerConfig } from '@shared/models' | 6 | import { ServerConfig } from '@shared/models' |
7 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
6 | import { | 8 | import { |
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' |
31 | import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../shared/extra-utils/server/servers' | 38 | import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers' |
32 | import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' | 39 | import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' |
33 | import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos' | 40 | import { |
41 | VideoDetails, | ||
42 | VideoImport, | ||
43 | VideoImportState, | ||
44 | VideoPlaylist, | ||
45 | VideoPlaylistPrivacy, | ||
46 | VideoPrivacy | ||
47 | } from '../../../shared/models/videos' | ||
34 | import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' | 48 | import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' |
35 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
36 | 49 | ||
37 | const expect = chai.expect | 50 | const 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 | }) |
diff --git a/server/tests/plugins/index.ts b/server/tests/plugins/index.ts index fd7116efd..4534120fd 100644 --- a/server/tests/plugins/index.ts +++ b/server/tests/plugins/index.ts | |||
@@ -7,5 +7,6 @@ import './plugin-helpers' | |||
7 | import './plugin-router' | 7 | import './plugin-router' |
8 | import './plugin-storage' | 8 | import './plugin-storage' |
9 | import './plugin-transcoding' | 9 | import './plugin-transcoding' |
10 | import './plugin-unloading' | ||
10 | import './translations' | 11 | import './translations' |
11 | import './video-constants' | 12 | import './video-constants' |
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts index a585e3020..325d20e84 100644 --- a/server/tests/plugins/plugin-helpers.ts +++ b/server/tests/plugins/plugin-helpers.ts | |||
@@ -12,7 +12,8 @@ import { | |||
12 | uploadVideoAndGetId, | 12 | uploadVideoAndGetId, |
13 | viewVideo, | 13 | viewVideo, |
14 | getVideosList, | 14 | getVideosList, |
15 | waitJobs | 15 | waitJobs, |
16 | makeGetRequest | ||
16 | } from '../../../shared/extra-utils' | 17 | } from '../../../shared/extra-utils' |
17 | import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers' | 18 | import { cleanupTests, flushAndRunMultipleServers, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers' |
18 | import { expect } from 'chai' | 19 | import { expect } from 'chai' |
@@ -68,6 +69,17 @@ describe('Test plugin helpers', function () { | |||
68 | it('Should have the correct webserver url', async function () { | 69 | it('Should have the correct webserver url', async function () { |
69 | await waitUntilLog(servers[0], `server url is http://localhost:${servers[0].port}`) | 70 | await waitUntilLog(servers[0], `server url is http://localhost:${servers[0].port}`) |
70 | }) | 71 | }) |
72 | |||
73 | it('Should have the correct config', async function () { | ||
74 | const res = await makeGetRequest({ | ||
75 | url: servers[0].url, | ||
76 | path: '/plugins/test-four/router/server-config', | ||
77 | statusCodeExpected: HttpStatusCode.OK_200 | ||
78 | }) | ||
79 | |||
80 | expect(res.body.serverConfig).to.exist | ||
81 | expect(res.body.serverConfig.instance.name).to.equal('PeerTube') | ||
82 | }) | ||
71 | }) | 83 | }) |
72 | 84 | ||
73 | describe('Server', function () { | 85 | describe('Server', function () { |
@@ -77,6 +89,19 @@ describe('Test plugin helpers', function () { | |||
77 | }) | 89 | }) |
78 | }) | 90 | }) |
79 | 91 | ||
92 | describe('Plugin', function () { | ||
93 | |||
94 | it('Should get the base static route', async function () { | ||
95 | const res = await makeGetRequest({ | ||
96 | url: servers[0].url, | ||
97 | path: '/plugins/test-four/router/static-route', | ||
98 | statusCodeExpected: HttpStatusCode.OK_200 | ||
99 | }) | ||
100 | |||
101 | expect(res.body.staticRoute).to.equal('/plugins/test-four/0.0.1/static/') | ||
102 | }) | ||
103 | }) | ||
104 | |||
80 | describe('Moderation', function () { | 105 | describe('Moderation', function () { |
81 | let videoUUIDServer1: string | 106 | let videoUUIDServer1: string |
82 | 107 | ||
diff --git a/server/tests/plugins/plugin-transcoding.ts b/server/tests/plugins/plugin-transcoding.ts index ecea21e69..c834b6985 100644 --- a/server/tests/plugins/plugin-transcoding.ts +++ b/server/tests/plugins/plugin-transcoding.ts | |||
@@ -15,6 +15,7 @@ import { | |||
15 | sendRTMPStreamInVideo, | 15 | sendRTMPStreamInVideo, |
16 | setAccessTokensToServers, | 16 | setAccessTokensToServers, |
17 | setDefaultVideoChannel, | 17 | setDefaultVideoChannel, |
18 | testFfmpegStreamError, | ||
18 | uninstallPlugin, | 19 | uninstallPlugin, |
19 | updateCustomSubConfig, | 20 | updateCustomSubConfig, |
20 | uploadVideoAndGetId, | 21 | uploadVideoAndGetId, |
@@ -119,8 +120,8 @@ describe('Test transcoding plugins', function () { | |||
119 | const res = await getConfig(server.url) | 120 | const res = await getConfig(server.url) |
120 | const config = res.body as ServerConfig | 121 | const config = res.body as ServerConfig |
121 | 122 | ||
122 | expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod' ]) | 123 | expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ]) |
123 | expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'low-live' ]) | 124 | expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'low-live', 'input-options-live', 'bad-scale-live' ]) |
124 | }) | 125 | }) |
125 | 126 | ||
126 | it('Should not use the plugin profile if not chosen by the admin', async function () { | 127 | it('Should not use the plugin profile if not chosen by the admin', async function () { |
@@ -143,6 +144,33 @@ describe('Test transcoding plugins', function () { | |||
143 | await checkVideoFPS(videoUUID, 'below', 12) | 144 | await checkVideoFPS(videoUUID, 'below', 12) |
144 | }) | 145 | }) |
145 | 146 | ||
147 | it('Should apply input options in vod profile', async function () { | ||
148 | this.timeout(120000) | ||
149 | |||
150 | await updateConf(server, 'input-options-vod', 'default') | ||
151 | |||
152 | const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid | ||
153 | await waitJobs([ server ]) | ||
154 | |||
155 | await checkVideoFPS(videoUUID, 'below', 6) | ||
156 | }) | ||
157 | |||
158 | it('Should apply the scale filter in vod profile', async function () { | ||
159 | this.timeout(120000) | ||
160 | |||
161 | await updateConf(server, 'bad-scale-vod', 'default') | ||
162 | |||
163 | const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid | ||
164 | await waitJobs([ server ]) | ||
165 | |||
166 | // Transcoding failed | ||
167 | const res = await getVideo(server.url, videoUUID) | ||
168 | const video: VideoDetails = res.body | ||
169 | |||
170 | expect(video.files).to.have.lengthOf(1) | ||
171 | expect(video.streamingPlaylists).to.have.lengthOf(0) | ||
172 | }) | ||
173 | |||
146 | it('Should not use the plugin profile if not chosen by the admin', async function () { | 174 | it('Should not use the plugin profile if not chosen by the admin', async function () { |
147 | this.timeout(120000) | 175 | this.timeout(120000) |
148 | 176 | ||
@@ -169,6 +197,31 @@ describe('Test transcoding plugins', function () { | |||
169 | await checkLiveFPS(liveVideoId, 'below', 12) | 197 | await checkLiveFPS(liveVideoId, 'below', 12) |
170 | }) | 198 | }) |
171 | 199 | ||
200 | it('Should apply the input options on live profile', async function () { | ||
201 | this.timeout(120000) | ||
202 | |||
203 | await updateConf(server, 'low-vod', 'input-options-live') | ||
204 | |||
205 | const liveVideoId = await createLiveWrapper(server) | ||
206 | |||
207 | await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm') | ||
208 | await waitUntilLivePublished(server.url, server.accessToken, liveVideoId) | ||
209 | await waitJobs([ server ]) | ||
210 | |||
211 | await checkLiveFPS(liveVideoId, 'below', 6) | ||
212 | }) | ||
213 | |||
214 | it('Should apply the scale filter name on live profile', async function () { | ||
215 | this.timeout(120000) | ||
216 | |||
217 | await updateConf(server, 'low-vod', 'bad-scale-live') | ||
218 | |||
219 | const liveVideoId = await createLiveWrapper(server) | ||
220 | |||
221 | const command = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm') | ||
222 | await testFfmpegStreamError(command, true) | ||
223 | }) | ||
224 | |||
172 | it('Should default to the default profile if the specified profile does not exist', async function () { | 225 | it('Should default to the default profile if the specified profile does not exist', async function () { |
173 | this.timeout(120000) | 226 | this.timeout(120000) |
174 | 227 | ||
diff --git a/server/tests/plugins/plugin-unloading.ts b/server/tests/plugins/plugin-unloading.ts new file mode 100644 index 000000000..74ca82e2f --- /dev/null +++ b/server/tests/plugins/plugin-unloading.ts | |||
@@ -0,0 +1,89 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import { | ||
5 | cleanupTests, | ||
6 | flushAndRunServer, | ||
7 | getPluginTestPath, | ||
8 | makeGetRequest, | ||
9 | installPlugin, | ||
10 | uninstallPlugin, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers | ||
13 | } from '../../../shared/extra-utils' | ||
14 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
15 | import { expect } from 'chai' | ||
16 | |||
17 | describe('Test plugins module unloading', function () { | ||
18 | let server: ServerInfo = null | ||
19 | const requestPath = '/plugins/test-unloading/router/get' | ||
20 | let value: string = null | ||
21 | |||
22 | before(async function () { | ||
23 | this.timeout(30000) | ||
24 | |||
25 | server = await flushAndRunServer(1) | ||
26 | await setAccessTokensToServers([ server ]) | ||
27 | |||
28 | await installPlugin({ | ||
29 | url: server.url, | ||
30 | accessToken: server.accessToken, | ||
31 | path: getPluginTestPath('-unloading') | ||
32 | }) | ||
33 | }) | ||
34 | |||
35 | it('Should return a numeric value', async function () { | ||
36 | const res = await makeGetRequest({ | ||
37 | url: server.url, | ||
38 | path: requestPath, | ||
39 | statusCodeExpected: HttpStatusCode.OK_200 | ||
40 | }) | ||
41 | |||
42 | expect(res.body.message).to.match(/^\d+$/) | ||
43 | value = res.body.message | ||
44 | }) | ||
45 | |||
46 | it('Should return the same value the second time', async function () { | ||
47 | const res = await makeGetRequest({ | ||
48 | url: server.url, | ||
49 | path: requestPath, | ||
50 | statusCodeExpected: HttpStatusCode.OK_200 | ||
51 | }) | ||
52 | |||
53 | expect(res.body.message).to.be.equal(value) | ||
54 | }) | ||
55 | |||
56 | it('Should uninstall the plugin and free the route', async function () { | ||
57 | await uninstallPlugin({ | ||
58 | url: server.url, | ||
59 | accessToken: server.accessToken, | ||
60 | npmName: 'peertube-plugin-test-unloading' | ||
61 | }) | ||
62 | |||
63 | await makeGetRequest({ | ||
64 | url: server.url, | ||
65 | path: requestPath, | ||
66 | statusCodeExpected: HttpStatusCode.NOT_FOUND_404 | ||
67 | }) | ||
68 | }) | ||
69 | |||
70 | it('Should return a different numeric value', async function () { | ||
71 | await installPlugin({ | ||
72 | url: server.url, | ||
73 | accessToken: server.accessToken, | ||
74 | path: getPluginTestPath('-unloading') | ||
75 | }) | ||
76 | const res = await makeGetRequest({ | ||
77 | url: server.url, | ||
78 | path: requestPath, | ||
79 | statusCodeExpected: HttpStatusCode.OK_200 | ||
80 | }) | ||
81 | |||
82 | expect(res.body.message).to.match(/^\d+$/) | ||
83 | expect(res.body.message).to.be.not.equal(value) | ||
84 | }) | ||
85 | |||
86 | after(async function () { | ||
87 | await cleanupTests([ server ]) | ||
88 | }) | ||
89 | }) | ||