diff options
Diffstat (limited to 'server/tests')
137 files changed, 5903 insertions, 3317 deletions
diff --git a/server/tests/activitypub.ts b/server/tests/activitypub.ts deleted file mode 100644 index 53a04d363..000000000 --- a/server/tests/activitypub.ts +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { flushTests, killallServers, makeActivityPubGetRequest, runServer, ServerInfo, setAccessTokensToServers } from './utils' | ||
6 | |||
7 | const expect = chai.expect | ||
8 | |||
9 | describe('Test activitypub', function () { | ||
10 | let server: ServerInfo = null | ||
11 | |||
12 | before(async function () { | ||
13 | this.timeout(30000) | ||
14 | |||
15 | await flushTests() | ||
16 | |||
17 | server = await runServer(1) | ||
18 | |||
19 | await setAccessTokensToServers([ server ]) | ||
20 | }) | ||
21 | |||
22 | it('Should return the account object', async function () { | ||
23 | const res = await makeActivityPubGetRequest(server.url, '/accounts/root') | ||
24 | const object = res.body | ||
25 | |||
26 | expect(object.type).to.equal('Person') | ||
27 | expect(object.id).to.equal('http://localhost:9001/accounts/root') | ||
28 | expect(object.name).to.equal('root') | ||
29 | expect(object.preferredUsername).to.equal('root') | ||
30 | }) | ||
31 | |||
32 | after(async function () { | ||
33 | killallServers([ server ]) | ||
34 | }) | ||
35 | }) | ||
diff --git a/server/tests/api/activitypub/client.ts b/server/tests/api/activitypub/client.ts new file mode 100644 index 000000000..6d90d8643 --- /dev/null +++ b/server/tests/api/activitypub/client.ts | |||
@@ -0,0 +1,67 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | doubleFollow, | ||
7 | flushAndRunMultipleServers, | ||
8 | flushTests, | ||
9 | killallServers, | ||
10 | makeActivityPubGetRequest, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers, | ||
13 | uploadVideo | ||
14 | } from '../../../../shared/utils' | ||
15 | |||
16 | const expect = chai.expect | ||
17 | |||
18 | describe('Test activitypub', function () { | ||
19 | let servers: ServerInfo[] = [] | ||
20 | let videoUUID: string | ||
21 | |||
22 | before(async function () { | ||
23 | this.timeout(30000) | ||
24 | |||
25 | await flushTests() | ||
26 | |||
27 | servers = await flushAndRunMultipleServers(2) | ||
28 | |||
29 | await setAccessTokensToServers(servers) | ||
30 | |||
31 | { | ||
32 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video' }) | ||
33 | videoUUID = res.body.video.uuid | ||
34 | } | ||
35 | |||
36 | await doubleFollow(servers[0], servers[1]) | ||
37 | }) | ||
38 | |||
39 | it('Should return the account object', async function () { | ||
40 | const res = await makeActivityPubGetRequest(servers[0].url, '/accounts/root') | ||
41 | const object = res.body | ||
42 | |||
43 | expect(object.type).to.equal('Person') | ||
44 | expect(object.id).to.equal('http://localhost:9001/accounts/root') | ||
45 | expect(object.name).to.equal('root') | ||
46 | expect(object.preferredUsername).to.equal('root') | ||
47 | }) | ||
48 | |||
49 | it('Should return the video object', async function () { | ||
50 | const res = await makeActivityPubGetRequest(servers[0].url, '/videos/watch/' + videoUUID) | ||
51 | const object = res.body | ||
52 | |||
53 | expect(object.type).to.equal('Video') | ||
54 | expect(object.id).to.equal('http://localhost:9001/videos/watch/' + videoUUID) | ||
55 | expect(object.name).to.equal('video') | ||
56 | }) | ||
57 | |||
58 | it('Should redirect to the origin video object', async function () { | ||
59 | const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, 302) | ||
60 | |||
61 | expect(res.header.location).to.equal('http://localhost:9001/videos/watch/' + videoUUID) | ||
62 | }) | ||
63 | |||
64 | after(async function () { | ||
65 | killallServers(servers) | ||
66 | }) | ||
67 | }) | ||
diff --git a/server/tests/api/activitypub/fetch.ts b/server/tests/api/activitypub/fetch.ts new file mode 100644 index 000000000..03609c1a9 --- /dev/null +++ b/server/tests/api/activitypub/fetch.ts | |||
@@ -0,0 +1,87 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | |||
5 | import { | ||
6 | createUser, | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | flushTests, | ||
10 | getVideosListSort, | ||
11 | killallServers, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | setActorField, | ||
15 | setVideoField, | ||
16 | uploadVideo, | ||
17 | userLogin, | ||
18 | waitJobs | ||
19 | } from '../../../../shared/utils' | ||
20 | import * as chai from 'chai' | ||
21 | import { Video } from '../../../../shared/models/videos' | ||
22 | |||
23 | const expect = chai.expect | ||
24 | |||
25 | describe('Test ActivityPub fetcher', function () { | ||
26 | let servers: ServerInfo[] | ||
27 | |||
28 | // --------------------------------------------------------------- | ||
29 | |||
30 | before(async function () { | ||
31 | this.timeout(60000) | ||
32 | |||
33 | servers = await flushAndRunMultipleServers(3) | ||
34 | |||
35 | // Get the access tokens | ||
36 | await setAccessTokensToServers(servers) | ||
37 | |||
38 | const user = { username: 'user1', password: 'password' } | ||
39 | for (const server of servers) { | ||
40 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
41 | } | ||
42 | |||
43 | const userAccessToken = await userLogin(servers[0], user) | ||
44 | |||
45 | await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video root' }) | ||
46 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'bad video root' }) | ||
47 | const badVideoUUID = res.body.video.uuid | ||
48 | await uploadVideo(servers[0].url, userAccessToken, { name: 'video user' }) | ||
49 | |||
50 | await setActorField(1, 'http://localhost:9001/accounts/user1', 'url', 'http://localhost:9002/accounts/user1') | ||
51 | await setVideoField(1, badVideoUUID, 'url', 'http://localhost:9003/videos/watch/' + badVideoUUID) | ||
52 | }) | ||
53 | |||
54 | it('Should add only the video with a valid actor URL', async function () { | ||
55 | this.timeout(60000) | ||
56 | |||
57 | await doubleFollow(servers[0], servers[1]) | ||
58 | await waitJobs(servers) | ||
59 | |||
60 | { | ||
61 | const res = await getVideosListSort(servers[0].url, 'createdAt') | ||
62 | expect(res.body.total).to.equal(3) | ||
63 | |||
64 | const data: Video[] = res.body.data | ||
65 | expect(data[0].name).to.equal('video root') | ||
66 | expect(data[1].name).to.equal('bad video root') | ||
67 | expect(data[2].name).to.equal('video user') | ||
68 | } | ||
69 | |||
70 | { | ||
71 | const res = await getVideosListSort(servers[1].url, 'createdAt') | ||
72 | expect(res.body.total).to.equal(1) | ||
73 | |||
74 | const data: Video[] = res.body.data | ||
75 | expect(data[0].name).to.equal('video root') | ||
76 | } | ||
77 | }) | ||
78 | |||
79 | after(async function () { | ||
80 | killallServers(servers) | ||
81 | |||
82 | // Keep the logs if the test failed | ||
83 | if (this['ok']) { | ||
84 | await flushTests() | ||
85 | } | ||
86 | }) | ||
87 | }) | ||
diff --git a/server/tests/api/activitypub/helpers.ts b/server/tests/api/activitypub/helpers.ts new file mode 100644 index 000000000..ac6e755c3 --- /dev/null +++ b/server/tests/api/activitypub/helpers.ts | |||
@@ -0,0 +1,182 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import { expect } from 'chai' | ||
5 | import { buildRequestStub } from '../../../../shared/utils/miscs/stubs' | ||
6 | import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../../../helpers/peertube-crypto' | ||
7 | import { cloneDeep } from 'lodash' | ||
8 | import { buildSignedActivity } from '../../../helpers/activitypub' | ||
9 | |||
10 | describe('Test activity pub helpers', function () { | ||
11 | describe('When checking the Linked Signature', function () { | ||
12 | |||
13 | it('Should fail with an invalid Mastodon signature', async function () { | ||
14 | const body = require('./json/mastodon/create-bad-signature.json') | ||
15 | const publicKey = require('./json/mastodon/public-key.json').publicKey | ||
16 | const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' } | ||
17 | |||
18 | const result = await isJsonLDSignatureVerified(fromActor as any, body) | ||
19 | |||
20 | expect(result).to.be.false | ||
21 | }) | ||
22 | |||
23 | it('Should fail with an invalid public key', async function () { | ||
24 | const body = require('./json/mastodon/create.json') | ||
25 | const publicKey = require('./json/mastodon/bad-public-key.json').publicKey | ||
26 | const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' } | ||
27 | |||
28 | const result = await isJsonLDSignatureVerified(fromActor as any, body) | ||
29 | |||
30 | expect(result).to.be.false | ||
31 | }) | ||
32 | |||
33 | it('Should succeed with a valid Mastodon signature', async function () { | ||
34 | const body = require('./json/mastodon/create.json') | ||
35 | const publicKey = require('./json/mastodon/public-key.json').publicKey | ||
36 | const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' } | ||
37 | |||
38 | const result = await isJsonLDSignatureVerified(fromActor as any, body) | ||
39 | |||
40 | expect(result).to.be.true | ||
41 | }) | ||
42 | |||
43 | it('Should fail with an invalid PeerTube signature', async function () { | ||
44 | const keys = require('./json/peertube/invalid-keys.json') | ||
45 | const body = require('./json/peertube/announce-without-context.json') | ||
46 | |||
47 | const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey } | ||
48 | const signedBody = await buildSignedActivity(actorSignature as any, body) | ||
49 | |||
50 | const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' } | ||
51 | const result = await isJsonLDSignatureVerified(fromActor as any, signedBody) | ||
52 | |||
53 | expect(result).to.be.false | ||
54 | }) | ||
55 | |||
56 | it('Should fail with an invalid PeerTube URL', async function () { | ||
57 | const keys = require('./json/peertube/keys.json') | ||
58 | const body = require('./json/peertube/announce-without-context.json') | ||
59 | |||
60 | const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey } | ||
61 | const signedBody = await buildSignedActivity(actorSignature as any, body) | ||
62 | |||
63 | const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9003/accounts/peertube' } | ||
64 | const result = await isJsonLDSignatureVerified(fromActor as any, signedBody) | ||
65 | |||
66 | expect(result).to.be.false | ||
67 | }) | ||
68 | |||
69 | it('Should succeed with a valid PeerTube signature', async function () { | ||
70 | const keys = require('./json/peertube/keys.json') | ||
71 | const body = require('./json/peertube/announce-without-context.json') | ||
72 | |||
73 | const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey } | ||
74 | const signedBody = await buildSignedActivity(actorSignature as any, body) | ||
75 | |||
76 | const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' } | ||
77 | const result = await isJsonLDSignatureVerified(fromActor as any, signedBody) | ||
78 | |||
79 | expect(result).to.be.true | ||
80 | }) | ||
81 | }) | ||
82 | |||
83 | describe('When checking HTTP signature', function () { | ||
84 | it('Should fail with an invalid http signature', async function () { | ||
85 | const req = buildRequestStub() | ||
86 | req.method = 'POST' | ||
87 | req.url = '/accounts/ronan/inbox' | ||
88 | |||
89 | const mastodonObject = cloneDeep(require('./json/mastodon/bad-http-signature.json')) | ||
90 | req.body = mastodonObject.body | ||
91 | req.headers = mastodonObject.headers | ||
92 | req.headers.signature = 'Signature ' + req.headers.signature | ||
93 | |||
94 | const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) | ||
95 | const publicKey = require('./json/mastodon/public-key.json').publicKey | ||
96 | |||
97 | const actor = { publicKey } | ||
98 | const verified = isHTTPSignatureVerified(parsed, actor as any) | ||
99 | |||
100 | expect(verified).to.be.false | ||
101 | }) | ||
102 | |||
103 | it('Should fail with an invalid public key', async function () { | ||
104 | const req = buildRequestStub() | ||
105 | req.method = 'POST' | ||
106 | req.url = '/accounts/ronan/inbox' | ||
107 | |||
108 | const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) | ||
109 | req.body = mastodonObject.body | ||
110 | req.headers = mastodonObject.headers | ||
111 | req.headers.signature = 'Signature ' + req.headers.signature | ||
112 | |||
113 | const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) | ||
114 | const publicKey = require('./json/mastodon/bad-public-key.json').publicKey | ||
115 | |||
116 | const actor = { publicKey } | ||
117 | const verified = isHTTPSignatureVerified(parsed, actor as any) | ||
118 | |||
119 | expect(verified).to.be.false | ||
120 | }) | ||
121 | |||
122 | it('Should fail because of clock skew', async function () { | ||
123 | const req = buildRequestStub() | ||
124 | req.method = 'POST' | ||
125 | req.url = '/accounts/ronan/inbox' | ||
126 | |||
127 | const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) | ||
128 | req.body = mastodonObject.body | ||
129 | req.headers = mastodonObject.headers | ||
130 | req.headers.signature = 'Signature ' + req.headers.signature | ||
131 | |||
132 | let errored = false | ||
133 | try { | ||
134 | parseHTTPSignature(req) | ||
135 | } catch { | ||
136 | errored = true | ||
137 | } | ||
138 | |||
139 | expect(errored).to.be.true | ||
140 | }) | ||
141 | |||
142 | it('Should fail without scheme', async function () { | ||
143 | const req = buildRequestStub() | ||
144 | req.method = 'POST' | ||
145 | req.url = '/accounts/ronan/inbox' | ||
146 | |||
147 | const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) | ||
148 | req.body = mastodonObject.body | ||
149 | req.headers = mastodonObject.headers | ||
150 | |||
151 | let errored = false | ||
152 | try { | ||
153 | parseHTTPSignature(req, 3600 * 1000 * 365 * 10) | ||
154 | } catch { | ||
155 | errored = true | ||
156 | } | ||
157 | |||
158 | expect(errored).to.be.true | ||
159 | }) | ||
160 | |||
161 | it('Should succeed with a valid signature', async function () { | ||
162 | const req = buildRequestStub() | ||
163 | req.method = 'POST' | ||
164 | req.url = '/accounts/ronan/inbox' | ||
165 | |||
166 | const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) | ||
167 | req.body = mastodonObject.body | ||
168 | req.headers = mastodonObject.headers | ||
169 | req.headers.signature = 'Signature ' + req.headers.signature | ||
170 | |||
171 | const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) | ||
172 | const publicKey = require('./json/mastodon/public-key.json').publicKey | ||
173 | |||
174 | const actor = { publicKey } | ||
175 | const verified = isHTTPSignatureVerified(parsed, actor as any) | ||
176 | |||
177 | expect(verified).to.be.true | ||
178 | }) | ||
179 | |||
180 | }) | ||
181 | |||
182 | }) | ||
diff --git a/server/tests/api/activitypub/index.ts b/server/tests/api/activitypub/index.ts new file mode 100644 index 000000000..450053309 --- /dev/null +++ b/server/tests/api/activitypub/index.ts | |||
@@ -0,0 +1,5 @@ | |||
1 | import './client' | ||
2 | import './fetch' | ||
3 | import './helpers' | ||
4 | import './refresher' | ||
5 | import './security' | ||
diff --git a/server/tests/api/activitypub/json/mastodon/bad-body-http-signature.json b/server/tests/api/activitypub/json/mastodon/bad-body-http-signature.json new file mode 100644 index 000000000..4e7bc3af5 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/bad-body-http-signature.json | |||
@@ -0,0 +1,93 @@ | |||
1 | { | ||
2 | "headers": { | ||
3 | "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)", | ||
4 | "host": "localhost", | ||
5 | "date": "Mon, 22 Oct 2018 13:34:22 GMT", | ||
6 | "accept-encoding": "gzip", | ||
7 | "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=", | ||
8 | "content-type": "application/activity+json", | ||
9 | "signature": "keyId=\"http://localhost:3000/users/ronan2#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"oLKbgxdFXdXsHJ3x/UsG9Svu7oa8Dyqiy6Jif4wqNuhAqRVMRaG18f+dd2OcfFX3XRGF8p8flZkU6vvoEQBauTwGRGcgXAJuKC1zYIWGk+PeiW8lNUnE4qGapWcTiFnIo7FKauNdsgqg/tvgs1pQIdHkDDjZMI64twP7sTN/4vG1PCq+kyqi/DM+ORLi/W7vFuLVHt2Iz7ikfw/R3/mMtS4FwLops+tVYBQ2iQ9DVRhTwLKVbeL/LLVB/tdGzNZ4F4nImBAQQ9I7WpPM6J/k+cBmoEbrUKs8ptx9gbX3OSsl5wlvPVMNzU9F9yb2MrB/Y/J4qssKz+LbiaktKGj7OQ==\"", | ||
10 | "content-length": "2815" | ||
11 | }, | ||
12 | "body": { | ||
13 | "@context": [ | ||
14 | "https://www.w3.org/ns/activitystreams", | ||
15 | "https://w3id.org/security/v1", | ||
16 | { | ||
17 | "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | ||
18 | "sensitive": "as:sensitive", | ||
19 | "movedTo": { | ||
20 | "@id": "as:movedTo", | ||
21 | "@type": "@id" | ||
22 | }, | ||
23 | "Hashtag": "as:Hashtag", | ||
24 | "ostatus": "http://ostatus.org#", | ||
25 | "atomUri": "ostatus:atomUri", | ||
26 | "inReplyToAtomUri": "ostatus:inReplyToAtomUri", | ||
27 | "conversation": "ostatus:conversation", | ||
28 | "toot": "http://joinmastodon.org/ns#", | ||
29 | "Emoji": "toot:Emoji", | ||
30 | "focalPoint": { | ||
31 | "@container": "@list", | ||
32 | "@id": "toot:focalPoint" | ||
33 | }, | ||
34 | "featured": { | ||
35 | "@id": "toot:featured", | ||
36 | "@type": "@id" | ||
37 | }, | ||
38 | "schema": "http://schema.org#", | ||
39 | "PropertyValue": "schema:PropertyValue", | ||
40 | "value": "schema:value" | ||
41 | } | ||
42 | ], | ||
43 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity", | ||
44 | "type": "Create", | ||
45 | "actor": "http://localhost:3000/users/ronan2", | ||
46 | "published": "2018-10-22T13:34:18Z", | ||
47 | "to": [ | ||
48 | "https://www.w3.org/ns/activitystreams#Public" | ||
49 | ], | ||
50 | "cc": [ | ||
51 | "http://localhost:3000/users/ronan2/followers", | ||
52 | "http://localhost:9000/accounts/ronan" | ||
53 | ], | ||
54 | "object": { | ||
55 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
56 | "type": "Note", | ||
57 | "summary": null, | ||
58 | "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
59 | "published": "2018-10-22T13:34:18Z", | ||
60 | "url": "http://localhost:3000/@ronan2/100939547203370948", | ||
61 | "attributedTo": "http://localhost:3000/users/ronan2", | ||
62 | "to": [ | ||
63 | "https://www.w3.org/ns/activitystreams#Public" | ||
64 | ], | ||
65 | "cc": [ | ||
66 | "http://localhost:3000/users/ronan2/followers", | ||
67 | "http://localhost:9000/accounts/ronan" | ||
68 | ], | ||
69 | "sensitive": false, | ||
70 | "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
71 | "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
72 | "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation", | ||
73 | "content": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>", | ||
74 | "contentMap": { | ||
75 | "en": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>" | ||
76 | }, | ||
77 | "attachment": [], | ||
78 | "tag": [ | ||
79 | { | ||
80 | "type": "Mention", | ||
81 | "href": "http://localhost:9000/accounts/ronan", | ||
82 | "name": "@ronan@localhost:9000" | ||
83 | } | ||
84 | ] | ||
85 | }, | ||
86 | "signature": { | ||
87 | "type": "RsaSignature2017", | ||
88 | "creator": "http://localhost:3000/users/ronan2#main-key", | ||
89 | "created": "2018-10-22T13:34:19Z", | ||
90 | "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q==" | ||
91 | } | ||
92 | } | ||
93 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/bad-http-signature.json b/server/tests/api/activitypub/json/mastodon/bad-http-signature.json new file mode 100644 index 000000000..098597db0 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/bad-http-signature.json | |||
@@ -0,0 +1,93 @@ | |||
1 | { | ||
2 | "headers": { | ||
3 | "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)", | ||
4 | "host": "localhost", | ||
5 | "date": "Mon, 22 Oct 2018 13:34:22 GMT", | ||
6 | "accept-encoding": "gzip", | ||
7 | "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=", | ||
8 | "content-type": "application/activity+json", | ||
9 | "signature": "keyId=\"http://localhost:3000/users/ronan2#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"oLKbgxdFXdXsHJ3x/UsG9Svu7oa8Dyqiy6Jif4wqNuhAqRVMRaG18f+dd2OcfFX3XRGF8p8flZkU6vvoEQBauTwGRGcgXAJuKC1zYIWGk+PeiW8lNUnE4qGapWcTiFnIo7FKauNdsgqg/tvgs1pQIdHkDDjZMI64twP7sTN/4vG1PCq+kyqi/DM+ORLi/W7vFuLVHt2Iz7ikfw/R3/mMtS4FwLops+tVYBQ2iQ9DVRhTwLKVbeL/LLVB/tdGzNZ4F4nImBAQQ9I7WpPM6J/k+cBmoEbrUKs8ptx9gbX3OSsl4wlvPVMNzU9F9yb2MrB/Y/J4qssKz+LbiaktKGj7OQ==\"", | ||
10 | "content-length": "2815" | ||
11 | }, | ||
12 | "body": { | ||
13 | "@context": [ | ||
14 | "https://www.w3.org/ns/activitystreams", | ||
15 | "https://w3id.org/security/v1", | ||
16 | { | ||
17 | "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | ||
18 | "sensitive": "as:sensitive", | ||
19 | "movedTo": { | ||
20 | "@id": "as:movedTo", | ||
21 | "@type": "@id" | ||
22 | }, | ||
23 | "Hashtag": "as:Hashtag", | ||
24 | "ostatus": "http://ostatus.org#", | ||
25 | "atomUri": "ostatus:atomUri", | ||
26 | "inReplyToAtomUri": "ostatus:inReplyToAtomUri", | ||
27 | "conversation": "ostatus:conversation", | ||
28 | "toot": "http://joinmastodon.org/ns#", | ||
29 | "Emoji": "toot:Emoji", | ||
30 | "focalPoint": { | ||
31 | "@container": "@list", | ||
32 | "@id": "toot:focalPoint" | ||
33 | }, | ||
34 | "featured": { | ||
35 | "@id": "toot:featured", | ||
36 | "@type": "@id" | ||
37 | }, | ||
38 | "schema": "http://schema.org#", | ||
39 | "PropertyValue": "schema:PropertyValue", | ||
40 | "value": "schema:value" | ||
41 | } | ||
42 | ], | ||
43 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity", | ||
44 | "type": "Create", | ||
45 | "actor": "http://localhost:3000/users/ronan2", | ||
46 | "published": "2018-10-22T13:34:18Z", | ||
47 | "to": [ | ||
48 | "https://www.w3.org/ns/activitystreams#Public" | ||
49 | ], | ||
50 | "cc": [ | ||
51 | "http://localhost:3000/users/ronan2/followers", | ||
52 | "http://localhost:9000/accounts/ronan" | ||
53 | ], | ||
54 | "object": { | ||
55 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
56 | "type": "Note", | ||
57 | "summary": null, | ||
58 | "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
59 | "published": "2018-10-22T13:34:18Z", | ||
60 | "url": "http://localhost:3000/@ronan2/100939547203370948", | ||
61 | "attributedTo": "http://localhost:3000/users/ronan2", | ||
62 | "to": [ | ||
63 | "https://www.w3.org/ns/activitystreams#Public" | ||
64 | ], | ||
65 | "cc": [ | ||
66 | "http://localhost:3000/users/ronan2/followers", | ||
67 | "http://localhost:9000/accounts/ronan" | ||
68 | ], | ||
69 | "sensitive": false, | ||
70 | "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
71 | "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
72 | "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation", | ||
73 | "content": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>", | ||
74 | "contentMap": { | ||
75 | "en": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>" | ||
76 | }, | ||
77 | "attachment": [], | ||
78 | "tag": [ | ||
79 | { | ||
80 | "type": "Mention", | ||
81 | "href": "http://localhost:9000/accounts/ronan", | ||
82 | "name": "@ronan@localhost:9000" | ||
83 | } | ||
84 | ] | ||
85 | }, | ||
86 | "signature": { | ||
87 | "type": "RsaSignature2017", | ||
88 | "creator": "http://localhost:3000/users/ronan2#main-key", | ||
89 | "created": "2018-10-22T13:34:19Z", | ||
90 | "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q==" | ||
91 | } | ||
92 | } | ||
93 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/bad-public-key.json b/server/tests/api/activitypub/json/mastodon/bad-public-key.json new file mode 100644 index 000000000..73d18b3ad --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/bad-public-key.json | |||
@@ -0,0 +1,3 @@ | |||
1 | { | ||
2 | "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0YyuthHtWWgDe0Fdgdp2\ndC5dTJsRqW6pFw5omIYYYjoES/WRewhVxEA54BhmxD3L1zChfx131N1TS8jVowhW\nm999jpUffKCCvLgYKIXETJDHiDeMONVx8wp7v9fS1HiFXo/E5und39gUMs14CMFZ\n6PE5jRV3r4XIKQJHQl7/X5n5FOb2934K+1TKUeBkbft/AushlKatYQakt3qHxpwx\nFvE+JjGo7QTnzdjaOx/e5QvojdGi2Kx4+jl77j2WVcSo5lOBz04OAVJtChtn82vS\nulPdDh3hZcDn+WK67yAhGP6AnzvOybZZS4zowlKiQ3kqjVVXKdl8gAsL4Y7MZ40R\nJQIDAQAB\n-----END PUBLIC KEY-----\n" | ||
3 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/create-bad-signature.json b/server/tests/api/activitypub/json/mastodon/create-bad-signature.json new file mode 100644 index 000000000..2cd037241 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/create-bad-signature.json | |||
@@ -0,0 +1,81 @@ | |||
1 | { | ||
2 | "@context": [ | ||
3 | "https://www.w3.org/ns/activitystreams", | ||
4 | "https://w3id.org/security/v1", | ||
5 | { | ||
6 | "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | ||
7 | "sensitive": "as:sensitive", | ||
8 | "movedTo": { | ||
9 | "@id": "as:movedTo", | ||
10 | "@type": "@id" | ||
11 | }, | ||
12 | "Hashtag": "as:Hashtag", | ||
13 | "ostatus": "http://ostatus.org#", | ||
14 | "atomUri": "ostatus:atomUri", | ||
15 | "inReplyToAtomUri": "ostatus:inReplyToAtomUri", | ||
16 | "conversation": "ostatus:conversation", | ||
17 | "toot": "http://joinmastodon.org/ns#", | ||
18 | "Emoji": "toot:Emoji", | ||
19 | "focalPoint": { | ||
20 | "@container": "@list", | ||
21 | "@id": "toot:focalPoint" | ||
22 | }, | ||
23 | "featured": { | ||
24 | "@id": "toot:featured", | ||
25 | "@type": "@id" | ||
26 | }, | ||
27 | "schema": "http://schema.org#", | ||
28 | "PropertyValue": "schema:PropertyValue", | ||
29 | "value": "schema:value" | ||
30 | } | ||
31 | ], | ||
32 | "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698/activity", | ||
33 | "type": "Create", | ||
34 | "actor": "http://localhost:3000/users/ronan2", | ||
35 | "published": "2018-10-22T12:43:07Z", | ||
36 | "to": [ | ||
37 | "https://www.w3.org/ns/activitystreams#Public" | ||
38 | ], | ||
39 | "cc": [ | ||
40 | "http://localhost:3000/users/ronan2/followers", | ||
41 | "http://localhost:9000/accounts/ronan" | ||
42 | ], | ||
43 | "object": { | ||
44 | "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698", | ||
45 | "type": "Note", | ||
46 | "summary": null, | ||
47 | "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
48 | "published": "2018-10-22T12:43:07Z", | ||
49 | "url": "http://localhost:3000/@ronan2/100939345950887698", | ||
50 | "attributedTo": "http://localhost:3000/users/ronan2", | ||
51 | "to": [ | ||
52 | "https://www.w3.org/ns/activitystreams#Public" | ||
53 | ], | ||
54 | "cc": [ | ||
55 | "http://localhost:3000/users/ronan2/followers", | ||
56 | "http://localhost:9000/accounts/ronan" | ||
57 | ], | ||
58 | "sensitive": false, | ||
59 | "atomUri": "http://localhost:3000/users/ronan2/statuses/100939345950887698", | ||
60 | "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
61 | "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation", | ||
62 | "content": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zerg</p>", | ||
63 | "contentMap": { | ||
64 | "en": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zerg</p>" | ||
65 | }, | ||
66 | "attachment": [], | ||
67 | "tag": [ | ||
68 | { | ||
69 | "type": "Mention", | ||
70 | "href": "http://localhost:9000/accounts/ronan", | ||
71 | "name": "@ronan@localhost:9000" | ||
72 | } | ||
73 | ] | ||
74 | }, | ||
75 | "signature": { | ||
76 | "type": "RsaSignature2017", | ||
77 | "creator": "http://localhost:3000/users/ronan2#main-key", | ||
78 | "created": "2018-10-22T12:43:08Z", | ||
79 | "signatureValue": "Vgr8nA0agPr9TcA4BlX+MWhmuE+rBcoIJLpnPbm3E5SnOCXbgjEfEaTLqfuzzkKNsR3PBbkvi3YWK4/DxJ0zmpzSB7yy4NRzluQMVQHqJiFKXAX3Sr3fIrK24xkWW9/F207c1NpFajSGbgnFKBdtFE0e5VqwSrSoOJkZukZW/2ATSnsyzblieuUmvTWpD0PqpUOsynPjw+RqZnqPn0cjw1z2Dm7ZRt3trnyMTXFYZw5U/YuqMY2kpadD6vq780md8kXlJIylxG6ZrlO2jz9fJdnfuVq43d4QFNsBm1K1r2WtNqX+i+wiqh+u3PjF4pzXtl/a3hJOH18IfZnK7I21mQ==" | ||
80 | } | ||
81 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/create.json b/server/tests/api/activitypub/json/mastodon/create.json new file mode 100644 index 000000000..0be271bb8 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/create.json | |||
@@ -0,0 +1,81 @@ | |||
1 | { | ||
2 | "@context": [ | ||
3 | "https://www.w3.org/ns/activitystreams", | ||
4 | "https://w3id.org/security/v1", | ||
5 | { | ||
6 | "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | ||
7 | "sensitive": "as:sensitive", | ||
8 | "movedTo": { | ||
9 | "@id": "as:movedTo", | ||
10 | "@type": "@id" | ||
11 | }, | ||
12 | "Hashtag": "as:Hashtag", | ||
13 | "ostatus": "http://ostatus.org#", | ||
14 | "atomUri": "ostatus:atomUri", | ||
15 | "inReplyToAtomUri": "ostatus:inReplyToAtomUri", | ||
16 | "conversation": "ostatus:conversation", | ||
17 | "toot": "http://joinmastodon.org/ns#", | ||
18 | "Emoji": "toot:Emoji", | ||
19 | "focalPoint": { | ||
20 | "@container": "@list", | ||
21 | "@id": "toot:focalPoint" | ||
22 | }, | ||
23 | "featured": { | ||
24 | "@id": "toot:featured", | ||
25 | "@type": "@id" | ||
26 | }, | ||
27 | "schema": "http://schema.org#", | ||
28 | "PropertyValue": "schema:PropertyValue", | ||
29 | "value": "schema:value" | ||
30 | } | ||
31 | ], | ||
32 | "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698/activity", | ||
33 | "type": "Create", | ||
34 | "actor": "http://localhost:3000/users/ronan2", | ||
35 | "published": "2018-10-22T12:43:07Z", | ||
36 | "to": [ | ||
37 | "https://www.w3.org/ns/activitystreams#Public" | ||
38 | ], | ||
39 | "cc": [ | ||
40 | "http://localhost:3000/users/ronan2/followers", | ||
41 | "http://localhost:9000/accounts/ronan" | ||
42 | ], | ||
43 | "object": { | ||
44 | "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698", | ||
45 | "type": "Note", | ||
46 | "summary": null, | ||
47 | "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
48 | "published": "2018-10-22T12:43:07Z", | ||
49 | "url": "http://localhost:3000/@ronan2/100939345950887698", | ||
50 | "attributedTo": "http://localhost:3000/users/ronan2", | ||
51 | "to": [ | ||
52 | "https://www.w3.org/ns/activitystreams#Public" | ||
53 | ], | ||
54 | "cc": [ | ||
55 | "http://localhost:3000/users/ronan2/followers", | ||
56 | "http://localhost:9000/accounts/ronan" | ||
57 | ], | ||
58 | "sensitive": false, | ||
59 | "atomUri": "http://localhost:3000/users/ronan2/statuses/100939345950887698", | ||
60 | "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
61 | "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation", | ||
62 | "content": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zerg</p>", | ||
63 | "contentMap": { | ||
64 | "en": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zerg</p>" | ||
65 | }, | ||
66 | "attachment": [], | ||
67 | "tag": [ | ||
68 | { | ||
69 | "type": "Mention", | ||
70 | "href": "http://localhost:9000/accounts/ronan", | ||
71 | "name": "@ronan@localhost:9000" | ||
72 | } | ||
73 | ] | ||
74 | }, | ||
75 | "signature": { | ||
76 | "type": "RsaSignature2017", | ||
77 | "creator": "http://localhost:3000/users/ronan2#main-key", | ||
78 | "created": "2018-10-22T12:43:08Z", | ||
79 | "signatureValue": "VgR8nA0agPr9TcA4BlX+MWhmuE+rBcoIJLpnPbm3E5SnOCXbgjEfEaTLqfuzzkKNsR3PBbkvi3YWK4/DxJ0zmpzSB7yy4NRzluQMVQHqJiFKXAX3Sr3fIrK24xkWW9/F207c1NpFajSGbgnFKBdtFE0e5VqwSrSoOJkZukZW/2ATSnsyzblieuUmvTWpD0PqpUOsynPjw+RqZnqPn0cjw1z2Dm7ZRt3trnyMTXFYZw5U/YuqMY2kpadD6vq780md8kXlJIylxG6ZrlO2jz9fJdnfuVq43d4QFNsBm1K1r2WtNqX+i+wiqh+u3PjF4pzXtl/a3hJOH18IfZnK7I21mQ==" | ||
80 | } | ||
81 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/http-signature.json b/server/tests/api/activitypub/json/mastodon/http-signature.json new file mode 100644 index 000000000..4e7bc3af5 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/http-signature.json | |||
@@ -0,0 +1,93 @@ | |||
1 | { | ||
2 | "headers": { | ||
3 | "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)", | ||
4 | "host": "localhost", | ||
5 | "date": "Mon, 22 Oct 2018 13:34:22 GMT", | ||
6 | "accept-encoding": "gzip", | ||
7 | "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=", | ||
8 | "content-type": "application/activity+json", | ||
9 | "signature": "keyId=\"http://localhost:3000/users/ronan2#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"oLKbgxdFXdXsHJ3x/UsG9Svu7oa8Dyqiy6Jif4wqNuhAqRVMRaG18f+dd2OcfFX3XRGF8p8flZkU6vvoEQBauTwGRGcgXAJuKC1zYIWGk+PeiW8lNUnE4qGapWcTiFnIo7FKauNdsgqg/tvgs1pQIdHkDDjZMI64twP7sTN/4vG1PCq+kyqi/DM+ORLi/W7vFuLVHt2Iz7ikfw/R3/mMtS4FwLops+tVYBQ2iQ9DVRhTwLKVbeL/LLVB/tdGzNZ4F4nImBAQQ9I7WpPM6J/k+cBmoEbrUKs8ptx9gbX3OSsl5wlvPVMNzU9F9yb2MrB/Y/J4qssKz+LbiaktKGj7OQ==\"", | ||
10 | "content-length": "2815" | ||
11 | }, | ||
12 | "body": { | ||
13 | "@context": [ | ||
14 | "https://www.w3.org/ns/activitystreams", | ||
15 | "https://w3id.org/security/v1", | ||
16 | { | ||
17 | "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", | ||
18 | "sensitive": "as:sensitive", | ||
19 | "movedTo": { | ||
20 | "@id": "as:movedTo", | ||
21 | "@type": "@id" | ||
22 | }, | ||
23 | "Hashtag": "as:Hashtag", | ||
24 | "ostatus": "http://ostatus.org#", | ||
25 | "atomUri": "ostatus:atomUri", | ||
26 | "inReplyToAtomUri": "ostatus:inReplyToAtomUri", | ||
27 | "conversation": "ostatus:conversation", | ||
28 | "toot": "http://joinmastodon.org/ns#", | ||
29 | "Emoji": "toot:Emoji", | ||
30 | "focalPoint": { | ||
31 | "@container": "@list", | ||
32 | "@id": "toot:focalPoint" | ||
33 | }, | ||
34 | "featured": { | ||
35 | "@id": "toot:featured", | ||
36 | "@type": "@id" | ||
37 | }, | ||
38 | "schema": "http://schema.org#", | ||
39 | "PropertyValue": "schema:PropertyValue", | ||
40 | "value": "schema:value" | ||
41 | } | ||
42 | ], | ||
43 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity", | ||
44 | "type": "Create", | ||
45 | "actor": "http://localhost:3000/users/ronan2", | ||
46 | "published": "2018-10-22T13:34:18Z", | ||
47 | "to": [ | ||
48 | "https://www.w3.org/ns/activitystreams#Public" | ||
49 | ], | ||
50 | "cc": [ | ||
51 | "http://localhost:3000/users/ronan2/followers", | ||
52 | "http://localhost:9000/accounts/ronan" | ||
53 | ], | ||
54 | "object": { | ||
55 | "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
56 | "type": "Note", | ||
57 | "summary": null, | ||
58 | "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
59 | "published": "2018-10-22T13:34:18Z", | ||
60 | "url": "http://localhost:3000/@ronan2/100939547203370948", | ||
61 | "attributedTo": "http://localhost:3000/users/ronan2", | ||
62 | "to": [ | ||
63 | "https://www.w3.org/ns/activitystreams#Public" | ||
64 | ], | ||
65 | "cc": [ | ||
66 | "http://localhost:3000/users/ronan2/followers", | ||
67 | "http://localhost:9000/accounts/ronan" | ||
68 | ], | ||
69 | "sensitive": false, | ||
70 | "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948", | ||
71 | "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752", | ||
72 | "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation", | ||
73 | "content": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>", | ||
74 | "contentMap": { | ||
75 | "en": "<p><span class=\"h-card\"><a href=\"http://localhost:9000/accounts/ronan\" class=\"u-url mention\">@<span>ronan</span></a></span> zergzerg</p>" | ||
76 | }, | ||
77 | "attachment": [], | ||
78 | "tag": [ | ||
79 | { | ||
80 | "type": "Mention", | ||
81 | "href": "http://localhost:9000/accounts/ronan", | ||
82 | "name": "@ronan@localhost:9000" | ||
83 | } | ||
84 | ] | ||
85 | }, | ||
86 | "signature": { | ||
87 | "type": "RsaSignature2017", | ||
88 | "creator": "http://localhost:3000/users/ronan2#main-key", | ||
89 | "created": "2018-10-22T13:34:19Z", | ||
90 | "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q==" | ||
91 | } | ||
92 | } | ||
93 | } | ||
diff --git a/server/tests/api/activitypub/json/mastodon/public-key.json b/server/tests/api/activitypub/json/mastodon/public-key.json new file mode 100644 index 000000000..b7b9b8308 --- /dev/null +++ b/server/tests/api/activitypub/json/mastodon/public-key.json | |||
@@ -0,0 +1,3 @@ | |||
1 | { | ||
2 | "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0YyuthHtWWgDe0Fdgdp2\ndC5dTJsRqW6pFw5omIYYYjoES/WRewhVxEA54BhmxD3L1zChfx131N1TS8jVowhW\nm999jpUffKCCvLgYKIXETJDHiDeMONVx8wp7v9fS1HiFXo/E5und39gUMs14CMFZ\n6PE5jRV3r4XIKQJHQl7/X5n5FOb2934K+1TKUeBkbft/AushlKatYQakt3qHxpwx\nFvE+JjGo7QTnzdjaOx/e5QvojdGi2Kx4+jl87j2WVcSo5lOBz04OAVJtChtn82vS\nulPdDh3hZcDn+WK67yAhGP6AnzvOybZZS4zowlKiQ3kqjVVXKdl8gAsL4Y7MZ40R\nJQIDAQAB\n-----END PUBLIC KEY-----\n" | ||
3 | } | ||
diff --git a/server/tests/api/activitypub/json/peertube/announce-without-context.json b/server/tests/api/activitypub/json/peertube/announce-without-context.json new file mode 100644 index 000000000..5f2af0cde --- /dev/null +++ b/server/tests/api/activitypub/json/peertube/announce-without-context.json | |||
@@ -0,0 +1,13 @@ | |||
1 | { | ||
2 | "type": "Announce", | ||
3 | "id": "http://localhost:9002/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05/announces/1", | ||
4 | "actor": "http://localhost:9002/accounts/peertube", | ||
5 | "object": "http://localhost:9002/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05", | ||
6 | "to": [ | ||
7 | "https://www.w3.org/ns/activitystreams#Public", | ||
8 | "http://localhost:9002/accounts/peertube/followers", | ||
9 | "http://localhost:9002/video-channels/root_channel/followers", | ||
10 | "http://localhost:9002/accounts/root/followers" | ||
11 | ], | ||
12 | "cc": [] | ||
13 | } | ||
diff --git a/server/tests/api/activitypub/json/peertube/invalid-keys.json b/server/tests/api/activitypub/json/peertube/invalid-keys.json new file mode 100644 index 000000000..0544e96b9 --- /dev/null +++ b/server/tests/api/activitypub/json/peertube/invalid-keys.json | |||
@@ -0,0 +1,6 @@ | |||
1 | { | ||
2 | "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqjQGdH6D3naKmSbbr/Df\nEh1H42F3WlHYXuxKLkm5Bemjdde+GwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYO\nwAyc3Zoy7afPNa4bZXqhJ1Im41rMGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55s\nIkczDkseJuadTvG+A1e4uNY2lnRmVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/F\npP5S75TS5l1DfJQIq2lp8RwrH6FvGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM\n7mS7eP8zF8lKXYUu8cjIscKm+XqGmyRoPyw2Pp53tew29idRUocVQHGBnlNbpKdd\naQIDAQAB\n-----END PUBLIC KEY-----\n", | ||
3 | "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAqjQGdH6D3naKmSbbr/DfEh1H42F3WlHYXuxKLkm5Bemjdde+\nGwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYOwAyc3Zoy7afPNa4bZXqhJ1Im41rM\nGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55sIkczDkseJuadTvG+A1e4uNY2lnRm\nVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/FpP5S75TS5l1DfJQIq2lp8RwrH6Fv\nGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM7mS7eP8zF8lKXYUu8cjIscKm+XqG\nmyRoPyw3Pp53tew29idRUocVQHGBnlNbpKddaQIDAQABAoIBAQCnBZawCtbtH/ay\ng+dhqEW/SOyavbKZ92cU/1tsQPxISRYXNjdf2VfK7HmVqC2S7NqBanz+AVZPHmda\n7OfamkSvQbFN5VvEy8ATNV+9HbG3HG78/MT9hZcGigmyJkcZuy4wILgoXCxfpxlD\netla60PB/4yioiRcmEIWjjOgpByphDJ7RuuuptyEvgjUjpPtvHK47O/loaD2HFJk\nbIYbRirbjUjITRjQxGVIvanqiwPG9pB26YDLxDOoXEumcnzRcEFWNdvoleaLgquS\nn/zVsXWEq4+1i7t44DDstWUt/2Bw5ksIkSdayQ6oy3vzre3YFHwvbVZ7qtQQgpru\nx+NIolZhAoGBAN1RgNj8zy9Py3SJdsoXtnuCItfD7eo7LWXUa06cM/NS695Q+/to\naa5i3cJnRlv+b+b3VvnhkhIBLfFQW+hWwPnnxJEehcm09ddN9zbWrZ4Yv9yYu+8d\nTLGyWL8kPFF1dz+29DcrSv3tXEOwxByX/O4U/X/i3wl2WhkybxVFnCuvAoGBAMTf\n91BgLzvcYKOxH+vRPOJY7g2HKGFe35R91M4E+9Eq1rq4LUQHBb3fhRh4+scNu0yb\nNfN1Zdx2nbgCXdTKomF1Ahxp58/A2iU65vVzL6hYfWXEGSmoBqsGCIpIxQ9jgB9k\nCl7t/Ban8Z/ORHTjI9fpHlSZyCWJ3ajepiM2a1ZnAoGAPpDO6wi1DXvyWVSPF1yS\nwuGsNfD2rjPihpoBZ+yypwP3GBcu1QjUb28Vn+KQOmt4eQPNO8DwCVT6BvEfulPk\nJAHISPom+jnFEgPBcmhIFpyKiLNI1bUjvExd2FNHFgQuHP38ligQAC782Un8dtTk\ntO2MKH4bbVJe8CaYzpuqJZMCgYABZyMpBHZxs8FQiUuT75rCdiXEHOlxwC5RrY/d\no/VzaR28mOFhsbcdwkD9iqcm0fc6tYRt5rFCH+pBzGqEwKjljuLj9vE67sHfMAtD\nRn3Zcj/6gKo5PMRHZbSb36bf1DKuhpT4VjPMqYe0PtEIEDJKMJQRwELH2bKlqGiA\nqbucEwKBgQCkS85JnpHEV/tSylsEEn2W3CQCx58zl7iZNV7h/tWMR4AyrcI0HqP6\nllJ7V/Cfw66MgelPnosKgagwLVI6gsqDtjnzYo3XuMRVlYIySJ/jV3eiUNkV2Ky2\nfp/gA9sVgp38QSr+xB9E0LNStcbqDzoCCcDRws/SK7PbkQH9KV47tQ==\n-----END RSA PRIVATE KEY-----" | ||
4 | } | ||
5 | |||
6 | |||
diff --git a/server/tests/api/activitypub/json/peertube/keys.json b/server/tests/api/activitypub/json/peertube/keys.json new file mode 100644 index 000000000..1a7700865 --- /dev/null +++ b/server/tests/api/activitypub/json/peertube/keys.json | |||
@@ -0,0 +1,4 @@ | |||
1 | { | ||
2 | "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqjQGdH6D3naKmSbbr/Df\nEh1H42F3WlHYXuxKLkm5Bemjdde+GwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYO\nwAyc3Zoy7afPNa4bZXqhJ1Im41rMGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55s\nIkczDkseJuadTvG+A1e4uNY2lnRmVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/F\npP5S75TS5l1DfJQIq2lp8RwrH6FvGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM\n7mS7eP8zF8lKXYUu8cjIscKm+XqGmyRoPyw3Pp53tew29idRUocVQHGBnlNbpKdd\naQIDAQAB\n-----END PUBLIC KEY-----\n", | ||
3 | "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAqjQGdH6D3naKmSbbr/DfEh1H42F3WlHYXuxKLkm5Bemjdde+\nGwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYOwAyc3Zoy7afPNa4bZXqhJ1Im41rM\nGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55sIkczDkseJuadTvG+A1e4uNY2lnRm\nVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/FpP5S75TS5l1DfJQIq2lp8RwrH6Fv\nGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM7mS7eP8zF8lKXYUu8cjIscKm+XqG\nmyRoPyw3Pp53tew29idRUocVQHGBnlNbpKddaQIDAQABAoIBAQCnBZawCtbtH/ay\ng+dhqEW/SOyavbKZ92cU/1tsQPxISRYXNjdf2VfK7HmVqC2S7NqBanz+AVZPHmda\n7OfamkSvQbFN5VvEy8ATNV+9HbG3HG78/MT9hZcGigmyJkcZuy4wILgoXCxfpxlD\netla60PB/4yioiRcmEIWjjOgpByphDJ7RuuuptyEvgjUjpPtvHK47O/loaD2HFJk\nbIYbRirbjUjITRjQxGVIvanqiwPG9pB26YDLxDOoXEumcnzRcEFWNdvoleaLgquS\nn/zVsXWEq4+1i7t44DDstWUt/2Bw5ksIkSdayQ6oy3vzre3YFHwvbVZ7qtQQgpru\nx+NIolZhAoGBAN1RgNj8zy9Py3SJdsoXtnuCItfD7eo7LWXUa06cM/NS695Q+/to\naa5i3cJnRlv+b+b3VvnhkhIBLfFQW+hWwPnnxJEehcm09ddN9zbWrZ4Yv9yYu+8d\nTLGyWL8kPFF1dz+29DcrSv3tXEOwxByX/O4U/X/i3wl2WhkybxVFnCuvAoGBAMTf\n91BgLzvcYKOxH+vRPOJY7g2HKGFe35R91M4E+9Eq1rq4LUQHBb3fhRh4+scNu0yb\nNfN1Zdx2nbgCXdTKomF1Ahxp58/A2iU65vVzL6hYfWXEGSmoBqsGCIpIxQ9jgB9k\nCl7t/Ban8Z/ORHTjI9fpHlSZyCWJ3ajepiM2a1ZnAoGAPpDO6wi1DXvyWVSPF1yS\nwuGsNfD2rjPihpoBZ+yypwP3GBcu1QjUb28Vn+KQOmt4eQPNO8DwCVT6BvEfulPk\nJAHISPom+jnFEgPBcmhIFpyKiLNI1bUjvExd2FNHFgQuHP38ligQAC782Un8dtTk\ntO2MKH4bbVJe8CaYzpuqJZMCgYABZyMpBHZxs8FQiUuT75rCdiXEHOlxwC5RrY/d\no/VzaR28mOFhsbcdwkD9iqcm0fc6tYRt5rFCH+pBzGqEwKjljuLj9vE67sHfMAtD\nRn3Zcj/6gKo5PMRHZbSb36bf1DKuhpT4VjPMqYe0PtEIEDJKMJQRwELH2bKlqGiA\nqbucEwKBgQCkS85JnpHEV/tSylsEEn2W3CQCx58zl7iZNV7h/tWMR4AyrcI0HqP6\nllJ7V/Cfw66MgelPnosKgagwLVI6gsqDtjnzYo3XuMRVlYIySJ/jV3eiUNkV2Ky2\nfp/gA9sVgp38QSr+xB9E0LNStcbqDzoCCcDRws/SK7PbkQH9KV47tQ==\n-----END RSA PRIVATE KEY-----" | ||
4 | } | ||
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts new file mode 100644 index 000000000..62ad8a0b5 --- /dev/null +++ b/server/tests/api/activitypub/refresher.ts | |||
@@ -0,0 +1,93 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import { | ||
5 | doubleFollow, | ||
6 | flushAndRunMultipleServers, | ||
7 | getVideo, | ||
8 | killallServers, | ||
9 | reRunServer, | ||
10 | ServerInfo, | ||
11 | setAccessTokensToServers, | ||
12 | uploadVideo, | ||
13 | wait, | ||
14 | setVideoField, | ||
15 | waitJobs | ||
16 | } from '../../../../shared/utils' | ||
17 | |||
18 | describe('Test AP refresher', function () { | ||
19 | let servers: ServerInfo[] = [] | ||
20 | let videoUUID1: string | ||
21 | let videoUUID2: string | ||
22 | let videoUUID3: string | ||
23 | |||
24 | before(async function () { | ||
25 | this.timeout(60000) | ||
26 | |||
27 | servers = await flushAndRunMultipleServers(2) | ||
28 | |||
29 | // Get the access tokens | ||
30 | await setAccessTokensToServers(servers) | ||
31 | |||
32 | { | ||
33 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video1' }) | ||
34 | videoUUID1 = res.body.video.uuid | ||
35 | } | ||
36 | |||
37 | { | ||
38 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video2' }) | ||
39 | videoUUID2 = res.body.video.uuid | ||
40 | } | ||
41 | |||
42 | { | ||
43 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video3' }) | ||
44 | videoUUID3 = res.body.video.uuid | ||
45 | } | ||
46 | |||
47 | await doubleFollow(servers[0], servers[1]) | ||
48 | }) | ||
49 | |||
50 | it('Should remove a deleted remote video', async function () { | ||
51 | this.timeout(60000) | ||
52 | |||
53 | await wait(10000) | ||
54 | |||
55 | // Change UUID so the remote server returns a 404 | ||
56 | await setVideoField(2, videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f') | ||
57 | |||
58 | await getVideo(servers[0].url, videoUUID1) | ||
59 | await getVideo(servers[0].url, videoUUID2) | ||
60 | |||
61 | await waitJobs(servers) | ||
62 | |||
63 | await getVideo(servers[0].url, videoUUID1, 404) | ||
64 | await getVideo(servers[0].url, videoUUID2, 200) | ||
65 | }) | ||
66 | |||
67 | it('Should not update a remote video if the remote instance is down', async function () { | ||
68 | this.timeout(60000) | ||
69 | |||
70 | killallServers([ servers[1] ]) | ||
71 | |||
72 | await setVideoField(2, videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e') | ||
73 | |||
74 | // Video will need a refresh | ||
75 | await wait(10000) | ||
76 | |||
77 | await getVideo(servers[0].url, videoUUID3) | ||
78 | // The refresh should fail | ||
79 | await waitJobs([ servers[0] ]) | ||
80 | |||
81 | await reRunServer(servers[1]) | ||
82 | |||
83 | // Should not refresh the video, even if the last refresh failed (to avoir a loop on dead instances) | ||
84 | await getVideo(servers[0].url, videoUUID3) | ||
85 | await waitJobs(servers) | ||
86 | |||
87 | await getVideo(servers[0].url, videoUUID3, 200) | ||
88 | }) | ||
89 | |||
90 | after(async function () { | ||
91 | killallServers(servers) | ||
92 | }) | ||
93 | }) | ||
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts new file mode 100644 index 000000000..342ae0fa1 --- /dev/null +++ b/server/tests/api/activitypub/security.ts | |||
@@ -0,0 +1,187 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | |||
5 | import { | ||
6 | flushAndRunMultipleServers, | ||
7 | flushTests, | ||
8 | killallServers, | ||
9 | makeFollowRequest, | ||
10 | makePOSTAPRequest, | ||
11 | ServerInfo, | ||
12 | setActorField | ||
13 | } from '../../../../shared/utils' | ||
14 | import { HTTP_SIGNATURE } from '../../../initializers' | ||
15 | import { buildDigest, buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activitypub-http-utils' | ||
16 | import * as chai from 'chai' | ||
17 | import { activityPubContextify, buildSignedActivity } from '../../../helpers/activitypub' | ||
18 | |||
19 | const expect = chai.expect | ||
20 | |||
21 | function setKeysOfServer2 (serverNumber: number, publicKey: string, privateKey: string) { | ||
22 | return Promise.all([ | ||
23 | setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'publicKey', publicKey), | ||
24 | setActorField(serverNumber, 'http://localhost:9002/accounts/peertube', 'privateKey', privateKey) | ||
25 | ]) | ||
26 | } | ||
27 | |||
28 | function setKeysOfServer3 (serverNumber: number, publicKey: string, privateKey: string) { | ||
29 | return Promise.all([ | ||
30 | setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'publicKey', publicKey), | ||
31 | setActorField(serverNumber, 'http://localhost:9003/accounts/peertube', 'privateKey', privateKey) | ||
32 | ]) | ||
33 | } | ||
34 | |||
35 | describe('Test ActivityPub security', function () { | ||
36 | let servers: ServerInfo[] | ||
37 | let url: string | ||
38 | |||
39 | const keys = require('./json/peertube/keys.json') | ||
40 | const invalidKeys = require('./json/peertube/invalid-keys.json') | ||
41 | const baseHttpSignature = { | ||
42 | algorithm: HTTP_SIGNATURE.ALGORITHM, | ||
43 | authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME, | ||
44 | keyId: 'acct:peertube@localhost:9002', | ||
45 | key: keys.privateKey, | ||
46 | headers: HTTP_SIGNATURE.HEADERS_TO_SIGN | ||
47 | } | ||
48 | |||
49 | // --------------------------------------------------------------- | ||
50 | |||
51 | before(async function () { | ||
52 | this.timeout(60000) | ||
53 | |||
54 | servers = await flushAndRunMultipleServers(3) | ||
55 | |||
56 | url = servers[0].url + '/inbox' | ||
57 | |||
58 | await setKeysOfServer2(1, keys.publicKey, keys.privateKey) | ||
59 | |||
60 | const to = { url: 'http://localhost:9001/accounts/peertube' } | ||
61 | const by = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey } | ||
62 | await makeFollowRequest(to, by) | ||
63 | }) | ||
64 | |||
65 | describe('When checking HTTP signature', function () { | ||
66 | |||
67 | it('Should fail with an invalid digest', async function () { | ||
68 | const body = activityPubContextify(require('./json/peertube/announce-without-context.json')) | ||
69 | const headers = { | ||
70 | Digest: buildDigest({ hello: 'coucou' }) | ||
71 | } | ||
72 | |||
73 | const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers) | ||
74 | |||
75 | expect(response.statusCode).to.equal(403) | ||
76 | }) | ||
77 | |||
78 | it('Should fail with an invalid date', async function () { | ||
79 | const body = activityPubContextify(require('./json/peertube/announce-without-context.json')) | ||
80 | const headers = buildGlobalHeaders(body) | ||
81 | headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT' | ||
82 | |||
83 | const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers) | ||
84 | |||
85 | expect(response.statusCode).to.equal(403) | ||
86 | }) | ||
87 | |||
88 | it('Should fail with bad keys', async function () { | ||
89 | await setKeysOfServer2(1, invalidKeys.publicKey, invalidKeys.privateKey) | ||
90 | await setKeysOfServer2(2, invalidKeys.publicKey, invalidKeys.privateKey) | ||
91 | |||
92 | const body = activityPubContextify(require('./json/peertube/announce-without-context.json')) | ||
93 | const headers = buildGlobalHeaders(body) | ||
94 | |||
95 | const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers) | ||
96 | |||
97 | expect(response.statusCode).to.equal(403) | ||
98 | }) | ||
99 | |||
100 | it('Should succeed with a valid HTTP signature', async function () { | ||
101 | await setKeysOfServer2(1, keys.publicKey, keys.privateKey) | ||
102 | await setKeysOfServer2(2, keys.publicKey, keys.privateKey) | ||
103 | |||
104 | const body = activityPubContextify(require('./json/peertube/announce-without-context.json')) | ||
105 | const headers = buildGlobalHeaders(body) | ||
106 | |||
107 | const { response } = await makePOSTAPRequest(url, body, baseHttpSignature, headers) | ||
108 | |||
109 | expect(response.statusCode).to.equal(204) | ||
110 | }) | ||
111 | }) | ||
112 | |||
113 | describe('When checking Linked Data Signature', function () { | ||
114 | before(async () => { | ||
115 | await setKeysOfServer3(3, keys.publicKey, keys.privateKey) | ||
116 | |||
117 | const to = { url: 'http://localhost:9001/accounts/peertube' } | ||
118 | const by = { url: 'http://localhost:9003/accounts/peertube', privateKey: keys.privateKey } | ||
119 | await makeFollowRequest(to, by) | ||
120 | }) | ||
121 | |||
122 | it('Should fail with bad keys', async function () { | ||
123 | this.timeout(10000) | ||
124 | |||
125 | await setKeysOfServer3(1, invalidKeys.publicKey, invalidKeys.privateKey) | ||
126 | await setKeysOfServer3(3, invalidKeys.publicKey, invalidKeys.privateKey) | ||
127 | |||
128 | const body = require('./json/peertube/announce-without-context.json') | ||
129 | body.actor = 'http://localhost:9003/accounts/peertube' | ||
130 | |||
131 | const signer: any = { privateKey: invalidKeys.privateKey, url: 'http://localhost:9003/accounts/peertube' } | ||
132 | const signedBody = await buildSignedActivity(signer, body) | ||
133 | |||
134 | const headers = buildGlobalHeaders(signedBody) | ||
135 | |||
136 | const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers) | ||
137 | |||
138 | expect(response.statusCode).to.equal(403) | ||
139 | }) | ||
140 | |||
141 | it('Should fail with an altered body', async function () { | ||
142 | this.timeout(10000) | ||
143 | |||
144 | await setKeysOfServer3(1, keys.publicKey, keys.privateKey) | ||
145 | await setKeysOfServer3(3, keys.publicKey, keys.privateKey) | ||
146 | |||
147 | const body = require('./json/peertube/announce-without-context.json') | ||
148 | body.actor = 'http://localhost:9003/accounts/peertube' | ||
149 | |||
150 | const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' } | ||
151 | const signedBody = await buildSignedActivity(signer, body) | ||
152 | |||
153 | signedBody.actor = 'http://localhost:9003/account/peertube' | ||
154 | |||
155 | const headers = buildGlobalHeaders(signedBody) | ||
156 | |||
157 | const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers) | ||
158 | |||
159 | expect(response.statusCode).to.equal(403) | ||
160 | }) | ||
161 | |||
162 | it('Should succeed with a valid signature', async function () { | ||
163 | this.timeout(10000) | ||
164 | |||
165 | const body = require('./json/peertube/announce-without-context.json') | ||
166 | body.actor = 'http://localhost:9003/accounts/peertube' | ||
167 | |||
168 | const signer: any = { privateKey: keys.privateKey, url: 'http://localhost:9003/accounts/peertube' } | ||
169 | const signedBody = await buildSignedActivity(signer, body) | ||
170 | |||
171 | const headers = buildGlobalHeaders(signedBody) | ||
172 | |||
173 | const { response } = await makePOSTAPRequest(url, signedBody, baseHttpSignature, headers) | ||
174 | |||
175 | expect(response.statusCode).to.equal(204) | ||
176 | }) | ||
177 | }) | ||
178 | |||
179 | after(async function () { | ||
180 | killallServers(servers) | ||
181 | |||
182 | // Keep the logs if the test failed | ||
183 | if (this['ok']) { | ||
184 | await flushTests() | ||
185 | } | ||
186 | }) | ||
187 | }) | ||
diff --git a/server/tests/api/check-params/accounts.ts b/server/tests/api/check-params/accounts.ts index 9e0b1e35c..68f9519c6 100644 --- a/server/tests/api/check-params/accounts.ts +++ b/server/tests/api/check-params/accounts.ts | |||
@@ -2,11 +2,15 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | 4 | ||
5 | import { flushTests, killallServers, runServer, ServerInfo } from '../../utils' | 5 | import { flushTests, killallServers, runServer, ServerInfo } from '../../../../shared/utils' |
6 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 6 | import { |
7 | import { getAccount } from '../../utils/users/accounts' | 7 | checkBadCountPagination, |
8 | 8 | checkBadSortPagination, | |
9 | describe('Test users API validators', function () { | 9 | checkBadStartPagination |
10 | } from '../../../../shared/utils/requests/check-api-params' | ||
11 | import { getAccount } from '../../../../shared/utils/users/accounts' | ||
12 | |||
13 | describe('Test accounts API validators', function () { | ||
10 | const path = '/api/v1/accounts/' | 14 | const path = '/api/v1/accounts/' |
11 | let server: ServerInfo | 15 | let server: ServerInfo |
12 | 16 | ||
diff --git a/server/tests/api/check-params/blocklist.ts b/server/tests/api/check-params/blocklist.ts new file mode 100644 index 000000000..c20453c16 --- /dev/null +++ b/server/tests/api/check-params/blocklist.ts | |||
@@ -0,0 +1,498 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | |||
5 | import { | ||
6 | createUser, | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | flushTests, | ||
10 | killallServers, | ||
11 | makeDeleteRequest, | ||
12 | makeGetRequest, | ||
13 | makePostBodyRequest, | ||
14 | ServerInfo, | ||
15 | setAccessTokensToServers, userLogin | ||
16 | } from '../../../../shared/utils' | ||
17 | import { | ||
18 | checkBadCountPagination, | ||
19 | checkBadSortPagination, | ||
20 | checkBadStartPagination | ||
21 | } from '../../../../shared/utils/requests/check-api-params' | ||
22 | |||
23 | describe('Test blocklist API validators', function () { | ||
24 | let servers: ServerInfo[] | ||
25 | let server: ServerInfo | ||
26 | let userAccessToken: string | ||
27 | |||
28 | before(async function () { | ||
29 | this.timeout(60000) | ||
30 | |||
31 | await flushTests() | ||
32 | |||
33 | servers = await flushAndRunMultipleServers(2) | ||
34 | await setAccessTokensToServers(servers) | ||
35 | |||
36 | server = servers[0] | ||
37 | |||
38 | const user = { username: 'user1', password: 'password' } | ||
39 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
40 | |||
41 | userAccessToken = await userLogin(server, user) | ||
42 | |||
43 | await doubleFollow(servers[0], servers[1]) | ||
44 | }) | ||
45 | |||
46 | // --------------------------------------------------------------- | ||
47 | |||
48 | describe('When managing user blocklist', function () { | ||
49 | |||
50 | describe('When managing user accounts blocklist', function () { | ||
51 | const path = '/api/v1/users/me/blocklist/accounts' | ||
52 | |||
53 | describe('When listing blocked accounts', function () { | ||
54 | it('Should fail with an unauthenticated user', async function () { | ||
55 | await makeGetRequest({ | ||
56 | url: server.url, | ||
57 | path, | ||
58 | statusCodeExpected: 401 | ||
59 | }) | ||
60 | }) | ||
61 | |||
62 | it('Should fail with a bad start pagination', async function () { | ||
63 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
64 | }) | ||
65 | |||
66 | it('Should fail with a bad count pagination', async function () { | ||
67 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
68 | }) | ||
69 | |||
70 | it('Should fail with an incorrect sort', async function () { | ||
71 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
72 | }) | ||
73 | }) | ||
74 | |||
75 | describe('When blocking an account', function () { | ||
76 | it('Should fail with an unauthenticated user', async function () { | ||
77 | await makePostBodyRequest({ | ||
78 | url: server.url, | ||
79 | path, | ||
80 | fields: { accountName: 'user1' }, | ||
81 | statusCodeExpected: 401 | ||
82 | }) | ||
83 | }) | ||
84 | |||
85 | it('Should fail with an unknown account', async function () { | ||
86 | await makePostBodyRequest({ | ||
87 | url: server.url, | ||
88 | token: server.accessToken, | ||
89 | path, | ||
90 | fields: { accountName: 'user2' }, | ||
91 | statusCodeExpected: 404 | ||
92 | }) | ||
93 | }) | ||
94 | |||
95 | it('Should fail to block ourselves', async function () { | ||
96 | await makePostBodyRequest({ | ||
97 | url: server.url, | ||
98 | token: server.accessToken, | ||
99 | path, | ||
100 | fields: { accountName: 'root' }, | ||
101 | statusCodeExpected: 409 | ||
102 | }) | ||
103 | }) | ||
104 | |||
105 | it('Should succeed with the correct params', async function () { | ||
106 | await makePostBodyRequest({ | ||
107 | url: server.url, | ||
108 | token: server.accessToken, | ||
109 | path, | ||
110 | fields: { accountName: 'user1' }, | ||
111 | statusCodeExpected: 204 | ||
112 | }) | ||
113 | }) | ||
114 | }) | ||
115 | |||
116 | describe('When unblocking an account', function () { | ||
117 | it('Should fail with an unauthenticated user', async function () { | ||
118 | await makeDeleteRequest({ | ||
119 | url: server.url, | ||
120 | path: path + '/user1', | ||
121 | statusCodeExpected: 401 | ||
122 | }) | ||
123 | }) | ||
124 | |||
125 | it('Should fail with an unknown account block', async function () { | ||
126 | await makeDeleteRequest({ | ||
127 | url: server.url, | ||
128 | path: path + '/user2', | ||
129 | token: server.accessToken, | ||
130 | statusCodeExpected: 404 | ||
131 | }) | ||
132 | }) | ||
133 | |||
134 | it('Should succeed with the correct params', async function () { | ||
135 | await makeDeleteRequest({ | ||
136 | url: server.url, | ||
137 | path: path + '/user1', | ||
138 | token: server.accessToken, | ||
139 | statusCodeExpected: 204 | ||
140 | }) | ||
141 | }) | ||
142 | }) | ||
143 | }) | ||
144 | |||
145 | describe('When managing user servers blocklist', function () { | ||
146 | const path = '/api/v1/users/me/blocklist/servers' | ||
147 | |||
148 | describe('When listing blocked servers', function () { | ||
149 | it('Should fail with an unauthenticated user', async function () { | ||
150 | await makeGetRequest({ | ||
151 | url: server.url, | ||
152 | path, | ||
153 | statusCodeExpected: 401 | ||
154 | }) | ||
155 | }) | ||
156 | |||
157 | it('Should fail with a bad start pagination', async function () { | ||
158 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
159 | }) | ||
160 | |||
161 | it('Should fail with a bad count pagination', async function () { | ||
162 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
163 | }) | ||
164 | |||
165 | it('Should fail with an incorrect sort', async function () { | ||
166 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
167 | }) | ||
168 | }) | ||
169 | |||
170 | describe('When blocking a server', function () { | ||
171 | it('Should fail with an unauthenticated user', async function () { | ||
172 | await makePostBodyRequest({ | ||
173 | url: server.url, | ||
174 | path, | ||
175 | fields: { host: 'localhost:9002' }, | ||
176 | statusCodeExpected: 401 | ||
177 | }) | ||
178 | }) | ||
179 | |||
180 | it('Should fail with an unknown server', async function () { | ||
181 | await makePostBodyRequest({ | ||
182 | url: server.url, | ||
183 | token: server.accessToken, | ||
184 | path, | ||
185 | fields: { host: 'localhost:9003' }, | ||
186 | statusCodeExpected: 404 | ||
187 | }) | ||
188 | }) | ||
189 | |||
190 | it('Should fail with our own server', async function () { | ||
191 | await makePostBodyRequest({ | ||
192 | url: server.url, | ||
193 | token: server.accessToken, | ||
194 | path, | ||
195 | fields: { host: 'localhost:9001' }, | ||
196 | statusCodeExpected: 409 | ||
197 | }) | ||
198 | }) | ||
199 | |||
200 | it('Should succeed with the correct params', async function () { | ||
201 | await makePostBodyRequest({ | ||
202 | url: server.url, | ||
203 | token: server.accessToken, | ||
204 | path, | ||
205 | fields: { host: 'localhost:9002' }, | ||
206 | statusCodeExpected: 204 | ||
207 | }) | ||
208 | }) | ||
209 | }) | ||
210 | |||
211 | describe('When unblocking a server', function () { | ||
212 | it('Should fail with an unauthenticated user', async function () { | ||
213 | await makeDeleteRequest({ | ||
214 | url: server.url, | ||
215 | path: path + '/localhost:9002', | ||
216 | statusCodeExpected: 401 | ||
217 | }) | ||
218 | }) | ||
219 | |||
220 | it('Should fail with an unknown server block', async function () { | ||
221 | await makeDeleteRequest({ | ||
222 | url: server.url, | ||
223 | path: path + '/localhost:9003', | ||
224 | token: server.accessToken, | ||
225 | statusCodeExpected: 404 | ||
226 | }) | ||
227 | }) | ||
228 | |||
229 | it('Should succeed with the correct params', async function () { | ||
230 | await makeDeleteRequest({ | ||
231 | url: server.url, | ||
232 | path: path + '/localhost:9002', | ||
233 | token: server.accessToken, | ||
234 | statusCodeExpected: 204 | ||
235 | }) | ||
236 | }) | ||
237 | }) | ||
238 | }) | ||
239 | }) | ||
240 | |||
241 | describe('When managing server blocklist', function () { | ||
242 | |||
243 | describe('When managing server accounts blocklist', function () { | ||
244 | const path = '/api/v1/server/blocklist/accounts' | ||
245 | |||
246 | describe('When listing blocked accounts', function () { | ||
247 | it('Should fail with an unauthenticated user', async function () { | ||
248 | await makeGetRequest({ | ||
249 | url: server.url, | ||
250 | path, | ||
251 | statusCodeExpected: 401 | ||
252 | }) | ||
253 | }) | ||
254 | |||
255 | it('Should fail with a user without the appropriate rights', async function () { | ||
256 | await makeGetRequest({ | ||
257 | url: server.url, | ||
258 | token: userAccessToken, | ||
259 | path, | ||
260 | statusCodeExpected: 403 | ||
261 | }) | ||
262 | }) | ||
263 | |||
264 | it('Should fail with a bad start pagination', async function () { | ||
265 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
266 | }) | ||
267 | |||
268 | it('Should fail with a bad count pagination', async function () { | ||
269 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
270 | }) | ||
271 | |||
272 | it('Should fail with an incorrect sort', async function () { | ||
273 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
274 | }) | ||
275 | }) | ||
276 | |||
277 | describe('When blocking an account', function () { | ||
278 | it('Should fail with an unauthenticated user', async function () { | ||
279 | await makePostBodyRequest({ | ||
280 | url: server.url, | ||
281 | path, | ||
282 | fields: { accountName: 'user1' }, | ||
283 | statusCodeExpected: 401 | ||
284 | }) | ||
285 | }) | ||
286 | |||
287 | it('Should fail with a user without the appropriate rights', async function () { | ||
288 | await makePostBodyRequest({ | ||
289 | url: server.url, | ||
290 | token: userAccessToken, | ||
291 | path, | ||
292 | fields: { accountName: 'user1' }, | ||
293 | statusCodeExpected: 403 | ||
294 | }) | ||
295 | }) | ||
296 | |||
297 | it('Should fail with an unknown account', async function () { | ||
298 | await makePostBodyRequest({ | ||
299 | url: server.url, | ||
300 | token: server.accessToken, | ||
301 | path, | ||
302 | fields: { accountName: 'user2' }, | ||
303 | statusCodeExpected: 404 | ||
304 | }) | ||
305 | }) | ||
306 | |||
307 | it('Should fail to block ourselves', async function () { | ||
308 | await makePostBodyRequest({ | ||
309 | url: server.url, | ||
310 | token: server.accessToken, | ||
311 | path, | ||
312 | fields: { accountName: 'root' }, | ||
313 | statusCodeExpected: 409 | ||
314 | }) | ||
315 | }) | ||
316 | |||
317 | it('Should succeed with the correct params', async function () { | ||
318 | await makePostBodyRequest({ | ||
319 | url: server.url, | ||
320 | token: server.accessToken, | ||
321 | path, | ||
322 | fields: { accountName: 'user1' }, | ||
323 | statusCodeExpected: 204 | ||
324 | }) | ||
325 | }) | ||
326 | }) | ||
327 | |||
328 | describe('When unblocking an account', function () { | ||
329 | it('Should fail with an unauthenticated user', async function () { | ||
330 | await makeDeleteRequest({ | ||
331 | url: server.url, | ||
332 | path: path + '/user1', | ||
333 | statusCodeExpected: 401 | ||
334 | }) | ||
335 | }) | ||
336 | |||
337 | it('Should fail with a user without the appropriate rights', async function () { | ||
338 | await makeDeleteRequest({ | ||
339 | url: server.url, | ||
340 | path: path + '/user1', | ||
341 | token: userAccessToken, | ||
342 | statusCodeExpected: 403 | ||
343 | }) | ||
344 | }) | ||
345 | |||
346 | it('Should fail with an unknown account block', async function () { | ||
347 | await makeDeleteRequest({ | ||
348 | url: server.url, | ||
349 | path: path + '/user2', | ||
350 | token: server.accessToken, | ||
351 | statusCodeExpected: 404 | ||
352 | }) | ||
353 | }) | ||
354 | |||
355 | it('Should succeed with the correct params', async function () { | ||
356 | await makeDeleteRequest({ | ||
357 | url: server.url, | ||
358 | path: path + '/user1', | ||
359 | token: server.accessToken, | ||
360 | statusCodeExpected: 204 | ||
361 | }) | ||
362 | }) | ||
363 | }) | ||
364 | }) | ||
365 | |||
366 | describe('When managing server servers blocklist', function () { | ||
367 | const path = '/api/v1/server/blocklist/servers' | ||
368 | |||
369 | describe('When listing blocked servers', function () { | ||
370 | it('Should fail with an unauthenticated user', async function () { | ||
371 | await makeGetRequest({ | ||
372 | url: server.url, | ||
373 | path, | ||
374 | statusCodeExpected: 401 | ||
375 | }) | ||
376 | }) | ||
377 | |||
378 | it('Should fail with a user without the appropriate rights', async function () { | ||
379 | await makeGetRequest({ | ||
380 | url: server.url, | ||
381 | token: userAccessToken, | ||
382 | path, | ||
383 | statusCodeExpected: 403 | ||
384 | }) | ||
385 | }) | ||
386 | |||
387 | it('Should fail with a bad start pagination', async function () { | ||
388 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
389 | }) | ||
390 | |||
391 | it('Should fail with a bad count pagination', async function () { | ||
392 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
393 | }) | ||
394 | |||
395 | it('Should fail with an incorrect sort', async function () { | ||
396 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
397 | }) | ||
398 | }) | ||
399 | |||
400 | describe('When blocking a server', function () { | ||
401 | it('Should fail with an unauthenticated user', async function () { | ||
402 | await makePostBodyRequest({ | ||
403 | url: server.url, | ||
404 | path, | ||
405 | fields: { host: 'localhost:9002' }, | ||
406 | statusCodeExpected: 401 | ||
407 | }) | ||
408 | }) | ||
409 | |||
410 | it('Should fail with a user without the appropriate rights', async function () { | ||
411 | await makePostBodyRequest({ | ||
412 | url: server.url, | ||
413 | token: userAccessToken, | ||
414 | path, | ||
415 | fields: { host: 'localhost:9002' }, | ||
416 | statusCodeExpected: 403 | ||
417 | }) | ||
418 | }) | ||
419 | |||
420 | it('Should fail with an unknown server', async function () { | ||
421 | await makePostBodyRequest({ | ||
422 | url: server.url, | ||
423 | token: server.accessToken, | ||
424 | path, | ||
425 | fields: { host: 'localhost:9003' }, | ||
426 | statusCodeExpected: 404 | ||
427 | }) | ||
428 | }) | ||
429 | |||
430 | it('Should fail with our own server', async function () { | ||
431 | await makePostBodyRequest({ | ||
432 | url: server.url, | ||
433 | token: server.accessToken, | ||
434 | path, | ||
435 | fields: { host: 'localhost:9001' }, | ||
436 | statusCodeExpected: 409 | ||
437 | }) | ||
438 | }) | ||
439 | |||
440 | it('Should succeed with the correct params', async function () { | ||
441 | await makePostBodyRequest({ | ||
442 | url: server.url, | ||
443 | token: server.accessToken, | ||
444 | path, | ||
445 | fields: { host: 'localhost:9002' }, | ||
446 | statusCodeExpected: 204 | ||
447 | }) | ||
448 | }) | ||
449 | }) | ||
450 | |||
451 | describe('When unblocking a server', function () { | ||
452 | it('Should fail with an unauthenticated user', async function () { | ||
453 | await makeDeleteRequest({ | ||
454 | url: server.url, | ||
455 | path: path + '/localhost:9002', | ||
456 | statusCodeExpected: 401 | ||
457 | }) | ||
458 | }) | ||
459 | |||
460 | it('Should fail with a user without the appropriate rights', async function () { | ||
461 | await makeDeleteRequest({ | ||
462 | url: server.url, | ||
463 | path: path + '/localhost:9002', | ||
464 | token: userAccessToken, | ||
465 | statusCodeExpected: 403 | ||
466 | }) | ||
467 | }) | ||
468 | |||
469 | it('Should fail with an unknown server block', async function () { | ||
470 | await makeDeleteRequest({ | ||
471 | url: server.url, | ||
472 | path: path + '/localhost:9003', | ||
473 | token: server.accessToken, | ||
474 | statusCodeExpected: 404 | ||
475 | }) | ||
476 | }) | ||
477 | |||
478 | it('Should succeed with the correct params', async function () { | ||
479 | await makeDeleteRequest({ | ||
480 | url: server.url, | ||
481 | path: path + '/localhost:9002', | ||
482 | token: server.accessToken, | ||
483 | statusCodeExpected: 204 | ||
484 | }) | ||
485 | }) | ||
486 | }) | ||
487 | }) | ||
488 | }) | ||
489 | |||
490 | after(async function () { | ||
491 | killallServers(servers) | ||
492 | |||
493 | // Keep the logs if the test failed | ||
494 | if (this['ok']) { | ||
495 | await flushTests() | ||
496 | } | ||
497 | }) | ||
498 | }) | ||
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index d807f910b..07de2b5a5 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts | |||
@@ -7,7 +7,7 @@ import { CustomConfig } from '../../../../shared/models/server/custom-config.mod | |||
7 | import { | 7 | import { |
8 | createUser, flushTests, killallServers, makeDeleteRequest, makeGetRequest, makePutBodyRequest, runServer, ServerInfo, | 8 | createUser, flushTests, killallServers, makeDeleteRequest, makeGetRequest, makePutBodyRequest, runServer, ServerInfo, |
9 | setAccessTokensToServers, userLogin, immutableAssign | 9 | setAccessTokensToServers, userLogin, immutableAssign |
10 | } from '../../utils' | 10 | } from '../../../../shared/utils' |
11 | 11 | ||
12 | describe('Test config API validators', function () { | 12 | describe('Test config API validators', function () { |
13 | const path = '/api/v1/config/custom' | 13 | const path = '/api/v1/config/custom' |
@@ -48,12 +48,16 @@ describe('Test config API validators', function () { | |||
48 | admin: { | 48 | admin: { |
49 | email: 'superadmin1@example.com' | 49 | email: 'superadmin1@example.com' |
50 | }, | 50 | }, |
51 | contactForm: { | ||
52 | enabled: false | ||
53 | }, | ||
51 | user: { | 54 | user: { |
52 | videoQuota: 5242881, | 55 | videoQuota: 5242881, |
53 | videoQuotaDaily: 318742 | 56 | videoQuotaDaily: 318742 |
54 | }, | 57 | }, |
55 | transcoding: { | 58 | transcoding: { |
56 | enabled: true, | 59 | enabled: true, |
60 | allowAdditionalExtensions: true, | ||
57 | threads: 1, | 61 | threads: 1, |
58 | resolutions: { | 62 | resolutions: { |
59 | '240p': false, | 63 | '240p': false, |
@@ -61,6 +65,9 @@ describe('Test config API validators', function () { | |||
61 | '480p': true, | 65 | '480p': true, |
62 | '720p': false, | 66 | '720p': false, |
63 | '1080p': false | 67 | '1080p': false |
68 | }, | ||
69 | hls: { | ||
70 | enabled: false | ||
64 | } | 71 | } |
65 | }, | 72 | }, |
66 | import: { | 73 | import: { |
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts new file mode 100644 index 000000000..c7e014b1f --- /dev/null +++ b/server/tests/api/check-params/contact-form.ts | |||
@@ -0,0 +1,96 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | |||
5 | import { | ||
6 | flushTests, | ||
7 | immutableAssign, | ||
8 | killallServers, | ||
9 | reRunServer, | ||
10 | runServer, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers | ||
13 | } from '../../../../shared/utils' | ||
14 | import { | ||
15 | checkBadCountPagination, | ||
16 | checkBadSortPagination, | ||
17 | checkBadStartPagination | ||
18 | } from '../../../../shared/utils/requests/check-api-params' | ||
19 | import { getAccount } from '../../../../shared/utils/users/accounts' | ||
20 | import { sendContactForm } from '../../../../shared/utils/server/contact-form' | ||
21 | import { MockSmtpServer } from '../../../../shared/utils/miscs/email' | ||
22 | |||
23 | describe('Test contact form API validators', function () { | ||
24 | let server: ServerInfo | ||
25 | const emails: object[] = [] | ||
26 | const defaultBody = { | ||
27 | fromName: 'super name', | ||
28 | fromEmail: 'toto@example.com', | ||
29 | body: 'Hello, how are you?' | ||
30 | } | ||
31 | |||
32 | // --------------------------------------------------------------- | ||
33 | |||
34 | before(async function () { | ||
35 | this.timeout(60000) | ||
36 | |||
37 | await flushTests() | ||
38 | await MockSmtpServer.Instance.collectEmails(emails) | ||
39 | |||
40 | // Email is disabled | ||
41 | server = await runServer(1) | ||
42 | }) | ||
43 | |||
44 | it('Should not accept a contact form if emails are disabled', async function () { | ||
45 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 })) | ||
46 | }) | ||
47 | |||
48 | it('Should not accept a contact form if it is disabled in the configuration', async function () { | ||
49 | this.timeout(10000) | ||
50 | |||
51 | killallServers([ server ]) | ||
52 | |||
53 | // Contact form is disabled | ||
54 | await reRunServer(server, { smtp: { hostname: 'localhost' }, contact_form: { enabled: false } }) | ||
55 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 })) | ||
56 | }) | ||
57 | |||
58 | it('Should not accept a contact form if from email is invalid', async function () { | ||
59 | this.timeout(10000) | ||
60 | |||
61 | killallServers([ server ]) | ||
62 | |||
63 | // Email & contact form enabled | ||
64 | await reRunServer(server, { smtp: { hostname: 'localhost' } }) | ||
65 | |||
66 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail' })) | ||
67 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail@' })) | ||
68 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: undefined })) | ||
69 | }) | ||
70 | |||
71 | it('Should not accept a contact form if from name is invalid', async function () { | ||
72 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: 'name'.repeat(100) })) | ||
73 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: '' })) | ||
74 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: undefined })) | ||
75 | }) | ||
76 | |||
77 | it('Should not accept a contact form if body is invalid', async function () { | ||
78 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'body'.repeat(5000) })) | ||
79 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'a' })) | ||
80 | await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: undefined })) | ||
81 | }) | ||
82 | |||
83 | it('Should accept a contact form with the correct parameters', async function () { | ||
84 | await sendContactForm(immutableAssign(defaultBody, { url: server.url })) | ||
85 | }) | ||
86 | |||
87 | after(async function () { | ||
88 | MockSmtpServer.Instance.kill() | ||
89 | killallServers([ server ]) | ||
90 | |||
91 | // Keep the logs if the test failed | ||
92 | if (this['ok']) { | ||
93 | await flushTests() | ||
94 | } | ||
95 | }) | ||
96 | }) | ||
diff --git a/server/tests/api/check-params/follows.ts b/server/tests/api/check-params/follows.ts index cdc95c81a..2ad1575a3 100644 --- a/server/tests/api/check-params/follows.ts +++ b/server/tests/api/check-params/follows.ts | |||
@@ -5,8 +5,12 @@ import 'mocha' | |||
5 | import { | 5 | import { |
6 | createUser, flushTests, killallServers, makeDeleteRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, | 6 | createUser, flushTests, killallServers, makeDeleteRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, |
7 | userLogin | 7 | userLogin |
8 | } from '../../utils' | 8 | } from '../../../../shared/utils' |
9 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 9 | import { |
10 | checkBadCountPagination, | ||
11 | checkBadSortPagination, | ||
12 | checkBadStartPagination | ||
13 | } from '../../../../shared/utils/requests/check-api-params' | ||
10 | 14 | ||
11 | describe('Test server follows API validators', function () { | 15 | describe('Test server follows API validators', function () { |
12 | let server: ServerInfo | 16 | let server: ServerInfo |
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index 71a217649..77c17036a 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts | |||
@@ -1,11 +1,13 @@ | |||
1 | // Order of the tests we want to execute | ||
2 | import './accounts' | 1 | import './accounts' |
2 | import './blocklist' | ||
3 | import './config' | 3 | import './config' |
4 | import './contact-form' | ||
4 | import './follows' | 5 | import './follows' |
5 | import './jobs' | 6 | import './jobs' |
6 | import './redundancy' | 7 | import './redundancy' |
7 | import './search' | 8 | import './search' |
8 | import './services' | 9 | import './services' |
10 | import './user-notifications' | ||
9 | import './user-subscriptions' | 11 | import './user-subscriptions' |
10 | import './users' | 12 | import './users' |
11 | import './video-abuses' | 13 | import './video-abuses' |
@@ -15,4 +17,5 @@ import './video-channels' | |||
15 | import './video-comments' | 17 | import './video-comments' |
16 | import './video-imports' | 18 | import './video-imports' |
17 | import './videos' | 19 | import './videos' |
20 | import './videos-filter' | ||
18 | import './videos-history' | 21 | import './videos-history' |
diff --git a/server/tests/api/check-params/jobs.ts b/server/tests/api/check-params/jobs.ts index ce3ac8809..89760ff98 100644 --- a/server/tests/api/check-params/jobs.ts +++ b/server/tests/api/check-params/jobs.ts | |||
@@ -2,9 +2,21 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | 4 | ||
5 | import { createUser, flushTests, killallServers, runServer, ServerInfo, setAccessTokensToServers, userLogin } from '../../utils' | 5 | import { |
6 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 6 | createUser, |
7 | import { makeGetRequest } from '../../utils/requests/requests' | 7 | flushTests, |
8 | killallServers, | ||
9 | runServer, | ||
10 | ServerInfo, | ||
11 | setAccessTokensToServers, | ||
12 | userLogin | ||
13 | } from '../../../../shared/utils' | ||
14 | import { | ||
15 | checkBadCountPagination, | ||
16 | checkBadSortPagination, | ||
17 | checkBadStartPagination | ||
18 | } from '../../../../shared/utils/requests/check-api-params' | ||
19 | import { makeGetRequest } from '../../../../shared/utils/requests/requests' | ||
8 | 20 | ||
9 | describe('Test jobs API validators', function () { | 21 | describe('Test jobs API validators', function () { |
10 | const path = '/api/v1/jobs/failed' | 22 | const path = '/api/v1/jobs/failed' |
diff --git a/server/tests/api/check-params/redundancy.ts b/server/tests/api/check-params/redundancy.ts index aa588e3dd..ff4726ceb 100644 --- a/server/tests/api/check-params/redundancy.ts +++ b/server/tests/api/check-params/redundancy.ts | |||
@@ -12,7 +12,7 @@ import { | |||
12 | ServerInfo, | 12 | ServerInfo, |
13 | setAccessTokensToServers, | 13 | setAccessTokensToServers, |
14 | userLogin | 14 | userLogin |
15 | } from '../../utils' | 15 | } from '../../../../shared/utils' |
16 | 16 | ||
17 | describe('Test server redundancy API validators', function () { | 17 | describe('Test server redundancy API validators', function () { |
18 | let servers: ServerInfo[] | 18 | let servers: ServerInfo[] |
diff --git a/server/tests/api/check-params/search.ts b/server/tests/api/check-params/search.ts index eabf602ac..aa81965f3 100644 --- a/server/tests/api/check-params/search.ts +++ b/server/tests/api/check-params/search.ts | |||
@@ -2,8 +2,12 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | 4 | ||
5 | import { flushTests, immutableAssign, killallServers, makeGetRequest, runServer, ServerInfo } from '../../utils' | 5 | import { flushTests, immutableAssign, killallServers, makeGetRequest, runServer, ServerInfo } from '../../../../shared/utils' |
6 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 6 | import { |
7 | checkBadCountPagination, | ||
8 | checkBadSortPagination, | ||
9 | checkBadStartPagination | ||
10 | } from '../../../../shared/utils/requests/check-api-params' | ||
7 | 11 | ||
8 | describe('Test videos API validator', function () { | 12 | describe('Test videos API validator', function () { |
9 | let server: ServerInfo | 13 | let server: ServerInfo |
diff --git a/server/tests/api/check-params/services.ts b/server/tests/api/check-params/services.ts index fcde7e179..28591af9d 100644 --- a/server/tests/api/check-params/services.ts +++ b/server/tests/api/check-params/services.ts | |||
@@ -2,7 +2,15 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | 4 | ||
5 | import { flushTests, killallServers, makeGetRequest, runServer, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../utils' | 5 | import { |
6 | flushTests, | ||
7 | killallServers, | ||
8 | makeGetRequest, | ||
9 | runServer, | ||
10 | ServerInfo, | ||
11 | setAccessTokensToServers, | ||
12 | uploadVideo | ||
13 | } from '../../../../shared/utils' | ||
6 | 14 | ||
7 | describe('Test services API validators', function () { | 15 | describe('Test services API validators', function () { |
8 | let server: ServerInfo | 16 | let server: ServerInfo |
diff --git a/server/tests/api/check-params/user-notifications.ts b/server/tests/api/check-params/user-notifications.ts new file mode 100644 index 000000000..714f481e9 --- /dev/null +++ b/server/tests/api/check-params/user-notifications.ts | |||
@@ -0,0 +1,297 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as io from 'socket.io-client' | ||
5 | |||
6 | import { | ||
7 | flushTests, | ||
8 | immutableAssign, | ||
9 | killallServers, | ||
10 | makeGetRequest, | ||
11 | makePostBodyRequest, | ||
12 | makePutBodyRequest, | ||
13 | runServer, | ||
14 | ServerInfo, | ||
15 | setAccessTokensToServers, | ||
16 | wait | ||
17 | } from '../../../../shared/utils' | ||
18 | import { | ||
19 | checkBadCountPagination, | ||
20 | checkBadSortPagination, | ||
21 | checkBadStartPagination | ||
22 | } from '../../../../shared/utils/requests/check-api-params' | ||
23 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../../../shared/models/users' | ||
24 | |||
25 | describe('Test user notifications API validators', function () { | ||
26 | let server: ServerInfo | ||
27 | |||
28 | // --------------------------------------------------------------- | ||
29 | |||
30 | before(async function () { | ||
31 | this.timeout(30000) | ||
32 | |||
33 | await flushTests() | ||
34 | |||
35 | server = await runServer(1) | ||
36 | |||
37 | await setAccessTokensToServers([ server ]) | ||
38 | }) | ||
39 | |||
40 | describe('When listing my notifications', function () { | ||
41 | const path = '/api/v1/users/me/notifications' | ||
42 | |||
43 | it('Should fail with a bad start pagination', async function () { | ||
44 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
45 | }) | ||
46 | |||
47 | it('Should fail with a bad count pagination', async function () { | ||
48 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
49 | }) | ||
50 | |||
51 | it('Should fail with an incorrect sort', async function () { | ||
52 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
53 | }) | ||
54 | |||
55 | it('Should fail with an incorrect unread parameter', async function () { | ||
56 | await makeGetRequest({ | ||
57 | url: server.url, | ||
58 | path, | ||
59 | query: { | ||
60 | unread: 'toto' | ||
61 | }, | ||
62 | token: server.accessToken, | ||
63 | statusCodeExpected: 200 | ||
64 | }) | ||
65 | }) | ||
66 | |||
67 | it('Should fail with a non authenticated user', async function () { | ||
68 | await makeGetRequest({ | ||
69 | url: server.url, | ||
70 | path, | ||
71 | statusCodeExpected: 401 | ||
72 | }) | ||
73 | }) | ||
74 | |||
75 | it('Should succeed with the correct parameters', async function () { | ||
76 | await makeGetRequest({ | ||
77 | url: server.url, | ||
78 | path, | ||
79 | token: server.accessToken, | ||
80 | statusCodeExpected: 200 | ||
81 | }) | ||
82 | }) | ||
83 | }) | ||
84 | |||
85 | describe('When marking as read my notifications', function () { | ||
86 | const path = '/api/v1/users/me/notifications/read' | ||
87 | |||
88 | it('Should fail with wrong ids parameters', async function () { | ||
89 | await makePostBodyRequest({ | ||
90 | url: server.url, | ||
91 | path, | ||
92 | fields: { | ||
93 | ids: [ 'hello' ] | ||
94 | }, | ||
95 | token: server.accessToken, | ||
96 | statusCodeExpected: 400 | ||
97 | }) | ||
98 | |||
99 | await makePostBodyRequest({ | ||
100 | url: server.url, | ||
101 | path, | ||
102 | fields: { | ||
103 | ids: [ ] | ||
104 | }, | ||
105 | token: server.accessToken, | ||
106 | statusCodeExpected: 400 | ||
107 | }) | ||
108 | |||
109 | await makePostBodyRequest({ | ||
110 | url: server.url, | ||
111 | path, | ||
112 | fields: { | ||
113 | ids: 5 | ||
114 | }, | ||
115 | token: server.accessToken, | ||
116 | statusCodeExpected: 400 | ||
117 | }) | ||
118 | }) | ||
119 | |||
120 | it('Should fail with a non authenticated user', async function () { | ||
121 | await makePostBodyRequest({ | ||
122 | url: server.url, | ||
123 | path, | ||
124 | fields: { | ||
125 | ids: [ 5 ] | ||
126 | }, | ||
127 | statusCodeExpected: 401 | ||
128 | }) | ||
129 | }) | ||
130 | |||
131 | it('Should succeed with the correct parameters', async function () { | ||
132 | await makePostBodyRequest({ | ||
133 | url: server.url, | ||
134 | path, | ||
135 | fields: { | ||
136 | ids: [ 5 ] | ||
137 | }, | ||
138 | token: server.accessToken, | ||
139 | statusCodeExpected: 204 | ||
140 | }) | ||
141 | }) | ||
142 | }) | ||
143 | |||
144 | describe('When marking as read my notifications', function () { | ||
145 | const path = '/api/v1/users/me/notifications/read-all' | ||
146 | |||
147 | it('Should fail with a non authenticated user', async function () { | ||
148 | await makePostBodyRequest({ | ||
149 | url: server.url, | ||
150 | path, | ||
151 | statusCodeExpected: 401 | ||
152 | }) | ||
153 | }) | ||
154 | |||
155 | it('Should succeed with the correct parameters', async function () { | ||
156 | await makePostBodyRequest({ | ||
157 | url: server.url, | ||
158 | path, | ||
159 | token: server.accessToken, | ||
160 | statusCodeExpected: 204 | ||
161 | }) | ||
162 | }) | ||
163 | }) | ||
164 | |||
165 | describe('When updating my notification settings', function () { | ||
166 | const path = '/api/v1/users/me/notification-settings' | ||
167 | const correctFields: UserNotificationSetting = { | ||
168 | newVideoFromSubscription: UserNotificationSettingValue.WEB, | ||
169 | newCommentOnMyVideo: UserNotificationSettingValue.WEB, | ||
170 | videoAbuseAsModerator: UserNotificationSettingValue.WEB, | ||
171 | blacklistOnMyVideo: UserNotificationSettingValue.WEB, | ||
172 | myVideoImportFinished: UserNotificationSettingValue.WEB, | ||
173 | myVideoPublished: UserNotificationSettingValue.WEB, | ||
174 | commentMention: UserNotificationSettingValue.WEB, | ||
175 | newFollow: UserNotificationSettingValue.WEB, | ||
176 | newUserRegistration: UserNotificationSettingValue.WEB | ||
177 | } | ||
178 | |||
179 | it('Should fail with missing fields', async function () { | ||
180 | await makePutBodyRequest({ | ||
181 | url: server.url, | ||
182 | path, | ||
183 | token: server.accessToken, | ||
184 | fields: { newVideoFromSubscription: UserNotificationSettingValue.WEB }, | ||
185 | statusCodeExpected: 400 | ||
186 | }) | ||
187 | }) | ||
188 | |||
189 | it('Should fail with incorrect field values', async function () { | ||
190 | { | ||
191 | const fields = immutableAssign(correctFields, { newCommentOnMyVideo: 15 }) | ||
192 | |||
193 | await makePutBodyRequest({ | ||
194 | url: server.url, | ||
195 | path, | ||
196 | token: server.accessToken, | ||
197 | fields, | ||
198 | statusCodeExpected: 400 | ||
199 | }) | ||
200 | } | ||
201 | |||
202 | { | ||
203 | const fields = immutableAssign(correctFields, { newCommentOnMyVideo: 'toto' }) | ||
204 | |||
205 | await makePutBodyRequest({ | ||
206 | url: server.url, | ||
207 | path, | ||
208 | fields, | ||
209 | token: server.accessToken, | ||
210 | statusCodeExpected: 400 | ||
211 | }) | ||
212 | } | ||
213 | }) | ||
214 | |||
215 | it('Should fail with a non authenticated user', async function () { | ||
216 | await makePutBodyRequest({ | ||
217 | url: server.url, | ||
218 | path, | ||
219 | fields: correctFields, | ||
220 | statusCodeExpected: 401 | ||
221 | }) | ||
222 | }) | ||
223 | |||
224 | it('Should succeed with the correct parameters', async function () { | ||
225 | await makePutBodyRequest({ | ||
226 | url: server.url, | ||
227 | path, | ||
228 | token: server.accessToken, | ||
229 | fields: correctFields, | ||
230 | statusCodeExpected: 204 | ||
231 | }) | ||
232 | }) | ||
233 | }) | ||
234 | |||
235 | describe('When connecting to my notification socket', function () { | ||
236 | it('Should fail with no token', function (next) { | ||
237 | const socket = io('http://localhost:9001/user-notifications', { reconnection: false }) | ||
238 | |||
239 | socket.on('error', () => { | ||
240 | socket.removeListener('error', this) | ||
241 | socket.disconnect() | ||
242 | next() | ||
243 | }) | ||
244 | |||
245 | socket.on('connect', () => { | ||
246 | socket.disconnect() | ||
247 | next(new Error('Connected with a missing token.')) | ||
248 | }) | ||
249 | }) | ||
250 | |||
251 | it('Should fail with an invalid token', function (next) { | ||
252 | const socket = io('http://localhost:9001/user-notifications', { | ||
253 | query: { accessToken: 'bad_access_token' }, | ||
254 | reconnection: false | ||
255 | }) | ||
256 | |||
257 | socket.on('error', () => { | ||
258 | socket.removeListener('error', this) | ||
259 | socket.disconnect() | ||
260 | next() | ||
261 | }) | ||
262 | |||
263 | socket.on('connect', () => { | ||
264 | socket.disconnect() | ||
265 | next(new Error('Connected with an invalid token.')) | ||
266 | }) | ||
267 | }) | ||
268 | |||
269 | it('Should success with the correct token', function (next) { | ||
270 | const socket = io('http://localhost:9001/user-notifications', { | ||
271 | query: { accessToken: server.accessToken }, | ||
272 | reconnection: false | ||
273 | }) | ||
274 | |||
275 | const errorListener = socket.on('error', err => { | ||
276 | next(new Error('Error in connection: ' + err)) | ||
277 | }) | ||
278 | |||
279 | socket.on('connect', async () => { | ||
280 | socket.removeListener('error', errorListener) | ||
281 | socket.disconnect() | ||
282 | |||
283 | await wait(500) | ||
284 | next() | ||
285 | }) | ||
286 | }) | ||
287 | }) | ||
288 | |||
289 | after(async function () { | ||
290 | killallServers([ server ]) | ||
291 | |||
292 | // Keep the logs if the test failed | ||
293 | if (this['ok']) { | ||
294 | await flushTests() | ||
295 | } | ||
296 | }) | ||
297 | }) | ||
diff --git a/server/tests/api/check-params/user-subscriptions.ts b/server/tests/api/check-params/user-subscriptions.ts index 9fba99ac8..8a9ced7c1 100644 --- a/server/tests/api/check-params/user-subscriptions.ts +++ b/server/tests/api/check-params/user-subscriptions.ts | |||
@@ -13,8 +13,14 @@ import { | |||
13 | ServerInfo, | 13 | ServerInfo, |
14 | setAccessTokensToServers, | 14 | setAccessTokensToServers, |
15 | userLogin | 15 | userLogin |
16 | } from '../../utils' | 16 | } from '../../../../shared/utils' |
17 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 17 | |
18 | import { | ||
19 | checkBadCountPagination, | ||
20 | checkBadSortPagination, | ||
21 | checkBadStartPagination | ||
22 | } from '../../../../shared/utils/requests/check-api-params' | ||
23 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
18 | 24 | ||
19 | describe('Test user subscriptions API validators', function () { | 25 | describe('Test user subscriptions API validators', function () { |
20 | const path = '/api/v1/users/me/subscriptions' | 26 | const path = '/api/v1/users/me/subscriptions' |
@@ -141,6 +147,8 @@ describe('Test user subscriptions API validators', function () { | |||
141 | }) | 147 | }) |
142 | 148 | ||
143 | it('Should succeed with the correct parameters', async function () { | 149 | it('Should succeed with the correct parameters', async function () { |
150 | this.timeout(20000) | ||
151 | |||
144 | await makePostBodyRequest({ | 152 | await makePostBodyRequest({ |
145 | url: server.url, | 153 | url: server.url, |
146 | path, | 154 | path, |
@@ -148,6 +156,8 @@ describe('Test user subscriptions API validators', function () { | |||
148 | fields: { uri: 'user1_channel@localhost:9001' }, | 156 | fields: { uri: 'user1_channel@localhost:9001' }, |
149 | statusCodeExpected: 204 | 157 | statusCodeExpected: 204 |
150 | }) | 158 | }) |
159 | |||
160 | await waitJobs([ server ]) | ||
151 | }) | 161 | }) |
152 | }) | 162 | }) |
153 | 163 | ||
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index cbfa0c137..13be8b460 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -9,11 +9,15 @@ import { | |||
9 | createUser, flushTests, getMyUserInformation, getMyUserVideoRating, getUsersList, immutableAssign, killallServers, makeGetRequest, | 9 | createUser, flushTests, getMyUserInformation, getMyUserVideoRating, getUsersList, immutableAssign, killallServers, makeGetRequest, |
10 | makePostBodyRequest, makeUploadRequest, makePutBodyRequest, registerUser, removeUser, runServer, ServerInfo, setAccessTokensToServers, | 10 | makePostBodyRequest, makeUploadRequest, makePutBodyRequest, registerUser, removeUser, runServer, ServerInfo, setAccessTokensToServers, |
11 | updateUser, uploadVideo, userLogin, deleteMe, unblockUser, blockUser | 11 | updateUser, uploadVideo, userLogin, deleteMe, unblockUser, blockUser |
12 | } from '../../utils' | 12 | } from '../../../../shared/utils' |
13 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 13 | import { |
14 | import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../utils/videos/video-imports' | 14 | checkBadCountPagination, |
15 | checkBadSortPagination, | ||
16 | checkBadStartPagination | ||
17 | } from '../../../../shared/utils/requests/check-api-params' | ||
18 | import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../../../shared/utils/videos/video-imports' | ||
15 | import { VideoPrivacy } from '../../../../shared/models/videos' | 19 | import { VideoPrivacy } from '../../../../shared/models/videos' |
16 | import { waitJobs } from '../../utils/server/jobs' | 20 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
17 | import { expect } from 'chai' | 21 | import { expect } from 'chai' |
18 | 22 | ||
19 | describe('Test users API validators', function () { | 23 | describe('Test users API validators', function () { |
@@ -99,13 +103,13 @@ describe('Test users API validators', function () { | |||
99 | } | 103 | } |
100 | 104 | ||
101 | it('Should fail with a too small username', async function () { | 105 | it('Should fail with a too small username', async function () { |
102 | const fields = immutableAssign(baseCorrectParams, { username: 'fi' }) | 106 | const fields = immutableAssign(baseCorrectParams, { username: '' }) |
103 | 107 | ||
104 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 108 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
105 | }) | 109 | }) |
106 | 110 | ||
107 | it('Should fail with a too long username', async function () { | 111 | it('Should fail with a too long username', async function () { |
108 | const fields = immutableAssign(baseCorrectParams, { username: 'my_super_username_which_is_very_long' }) | 112 | const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) }) |
109 | 113 | ||
110 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 114 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
111 | }) | 115 | }) |
@@ -304,6 +308,14 @@ describe('Test users API validators', function () { | |||
304 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | 308 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) |
305 | }) | 309 | }) |
306 | 310 | ||
311 | it('Should fail with an invalid videosHistoryEnabled attribute', async function () { | ||
312 | const fields = { | ||
313 | videosHistoryEnabled: -1 | ||
314 | } | ||
315 | |||
316 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | ||
317 | }) | ||
318 | |||
307 | it('Should fail with an non authenticated user', async function () { | 319 | it('Should fail with an non authenticated user', async function () { |
308 | const fields = { | 320 | const fields = { |
309 | currentPassword: 'my super password', | 321 | currentPassword: 'my super password', |
@@ -315,7 +327,7 @@ describe('Test users API validators', function () { | |||
315 | 327 | ||
316 | it('Should fail with a too long description', async function () { | 328 | it('Should fail with a too long description', async function () { |
317 | const fields = { | 329 | const fields = { |
318 | description: 'super'.repeat(60) | 330 | description: 'super'.repeat(201) |
319 | } | 331 | } |
320 | 332 | ||
321 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | 333 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) |
@@ -428,6 +440,14 @@ describe('Test users API validators', function () { | |||
428 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) | 440 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) |
429 | }) | 441 | }) |
430 | 442 | ||
443 | it('Should fail with an invalid emailVerified attribute', async function () { | ||
444 | const fields = { | ||
445 | emailVerified: 'yes' | ||
446 | } | ||
447 | |||
448 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) | ||
449 | }) | ||
450 | |||
431 | it('Should fail with an invalid videoQuota attribute', async function () { | 451 | it('Should fail with an invalid videoQuota attribute', async function () { |
432 | const fields = { | 452 | const fields = { |
433 | videoQuota: -90 | 453 | videoQuota: -90 |
@@ -444,6 +464,24 @@ describe('Test users API validators', function () { | |||
444 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) | 464 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) |
445 | }) | 465 | }) |
446 | 466 | ||
467 | it('Should fail with a too small password', async function () { | ||
468 | const fields = { | ||
469 | currentPassword: 'my super password', | ||
470 | password: 'bla' | ||
471 | } | ||
472 | |||
473 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) | ||
474 | }) | ||
475 | |||
476 | it('Should fail with a too long password', async function () { | ||
477 | const fields = { | ||
478 | currentPassword: 'my super password', | ||
479 | password: 'super'.repeat(61) | ||
480 | } | ||
481 | |||
482 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields }) | ||
483 | }) | ||
484 | |||
447 | it('Should fail with an non authenticated user', async function () { | 485 | it('Should fail with an non authenticated user', async function () { |
448 | const fields = { | 486 | const fields = { |
449 | videoQuota: 42 | 487 | videoQuota: 42 |
@@ -463,12 +501,12 @@ describe('Test users API validators', function () { | |||
463 | it('Should succeed with the correct params', async function () { | 501 | it('Should succeed with the correct params', async function () { |
464 | const fields = { | 502 | const fields = { |
465 | email: 'email@example.com', | 503 | email: 'email@example.com', |
504 | emailVerified: true, | ||
466 | videoQuota: 42, | 505 | videoQuota: 42, |
467 | role: UserRole.MODERATOR | 506 | role: UserRole.USER |
468 | } | 507 | } |
469 | 508 | ||
470 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 }) | 509 | await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 }) |
471 | userAccessToken = await userLogin(server, user) | ||
472 | }) | 510 | }) |
473 | }) | 511 | }) |
474 | 512 | ||
@@ -541,13 +579,13 @@ describe('Test users API validators', function () { | |||
541 | } | 579 | } |
542 | 580 | ||
543 | it('Should fail with a too small username', async function () { | 581 | it('Should fail with a too small username', async function () { |
544 | const fields = immutableAssign(baseCorrectParams, { username: 'ji' }) | 582 | const fields = immutableAssign(baseCorrectParams, { username: '' }) |
545 | 583 | ||
546 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | 584 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) |
547 | }) | 585 | }) |
548 | 586 | ||
549 | it('Should fail with a too long username', async function () { | 587 | it('Should fail with a too long username', async function () { |
550 | const fields = immutableAssign(baseCorrectParams, { username: 'my_super_username_which_is_very_long' }) | 588 | const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) }) |
551 | 589 | ||
552 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) | 590 | await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields }) |
553 | }) | 591 | }) |
diff --git a/server/tests/api/check-params/video-abuses.ts b/server/tests/api/check-params/video-abuses.ts index d2bed6a2a..3b8f5f14d 100644 --- a/server/tests/api/check-params/video-abuses.ts +++ b/server/tests/api/check-params/video-abuses.ts | |||
@@ -15,8 +15,12 @@ import { | |||
15 | updateVideoAbuse, | 15 | updateVideoAbuse, |
16 | uploadVideo, | 16 | uploadVideo, |
17 | userLogin | 17 | userLogin |
18 | } from '../../utils' | 18 | } from '../../../../shared/utils' |
19 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 19 | import { |
20 | checkBadCountPagination, | ||
21 | checkBadSortPagination, | ||
22 | checkBadStartPagination | ||
23 | } from '../../../../shared/utils/requests/check-api-params' | ||
20 | import { VideoAbuseState } from '../../../../shared/models/videos' | 24 | import { VideoAbuseState } from '../../../../shared/models/videos' |
21 | 25 | ||
22 | describe('Test video abuses API validators', function () { | 26 | describe('Test video abuses API validators', function () { |
@@ -109,8 +113,8 @@ describe('Test video abuses API validators', function () { | |||
109 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 113 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
110 | }) | 114 | }) |
111 | 115 | ||
112 | it('Should fail with a reason too big', async function () { | 116 | it('Should fail with a too big reason', async function () { |
113 | const fields = { reason: 'super'.repeat(61) } | 117 | const fields = { reason: 'super'.repeat(605) } |
114 | 118 | ||
115 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 119 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
116 | }) | 120 | }) |
@@ -150,7 +154,7 @@ describe('Test video abuses API validators', function () { | |||
150 | }) | 154 | }) |
151 | 155 | ||
152 | it('Should fail with a bad moderation comment', async function () { | 156 | it('Should fail with a bad moderation comment', async function () { |
153 | const body = { moderationComment: 'b'.repeat(305) } | 157 | const body = { moderationComment: 'b'.repeat(3001) } |
154 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId, body, 400) | 158 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId, body, 400) |
155 | }) | 159 | }) |
156 | 160 | ||
diff --git a/server/tests/api/check-params/video-blacklist.ts b/server/tests/api/check-params/video-blacklist.ts index 473216236..6b82643f4 100644 --- a/server/tests/api/check-params/video-blacklist.ts +++ b/server/tests/api/check-params/video-blacklist.ts | |||
@@ -4,25 +4,33 @@ import 'mocha' | |||
4 | 4 | ||
5 | import { | 5 | import { |
6 | createUser, | 6 | createUser, |
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
7 | flushTests, | 9 | flushTests, |
8 | getBlacklistedVideosList, getVideo, getVideoWithToken, | 10 | getBlacklistedVideosList, |
11 | getVideo, | ||
12 | getVideoWithToken, | ||
9 | killallServers, | 13 | killallServers, |
10 | makePostBodyRequest, | 14 | makePostBodyRequest, |
11 | makePutBodyRequest, | 15 | makePutBodyRequest, |
12 | removeVideoFromBlacklist, | 16 | removeVideoFromBlacklist, |
13 | runServer, | ||
14 | ServerInfo, | 17 | ServerInfo, |
15 | setAccessTokensToServers, | 18 | setAccessTokensToServers, |
16 | uploadVideo, | 19 | uploadVideo, |
17 | userLogin | 20 | userLogin, waitJobs |
18 | } from '../../utils' | 21 | } from '../../../../shared/utils' |
19 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 22 | import { |
23 | checkBadCountPagination, | ||
24 | checkBadSortPagination, | ||
25 | checkBadStartPagination | ||
26 | } from '../../../../shared/utils/requests/check-api-params' | ||
20 | import { VideoDetails } from '../../../../shared/models/videos' | 27 | import { VideoDetails } from '../../../../shared/models/videos' |
21 | import { expect } from 'chai' | 28 | import { expect } from 'chai' |
22 | 29 | ||
23 | describe('Test video blacklist API validators', function () { | 30 | describe('Test video blacklist API validators', function () { |
24 | let server: ServerInfo | 31 | let servers: ServerInfo[] |
25 | let notBlacklistedVideoId: number | 32 | let notBlacklistedVideoId: number |
33 | let remoteVideoUUID: string | ||
26 | let userAccessToken1 = '' | 34 | let userAccessToken1 = '' |
27 | let userAccessToken2 = '' | 35 | let userAccessToken2 = '' |
28 | 36 | ||
@@ -32,75 +40,89 @@ describe('Test video blacklist API validators', function () { | |||
32 | this.timeout(120000) | 40 | this.timeout(120000) |
33 | 41 | ||
34 | await flushTests() | 42 | await flushTests() |
43 | servers = await flushAndRunMultipleServers(2) | ||
35 | 44 | ||
36 | server = await runServer(1) | 45 | await setAccessTokensToServers(servers) |
37 | 46 | await doubleFollow(servers[0], servers[1]) | |
38 | await setAccessTokensToServers([ server ]) | ||
39 | 47 | ||
40 | { | 48 | { |
41 | const username = 'user1' | 49 | const username = 'user1' |
42 | const password = 'my super password' | 50 | const password = 'my super password' |
43 | await createUser(server.url, server.accessToken, username, password) | 51 | await createUser(servers[0].url, servers[0].accessToken, username, password) |
44 | userAccessToken1 = await userLogin(server, { username, password }) | 52 | userAccessToken1 = await userLogin(servers[0], { username, password }) |
45 | } | 53 | } |
46 | 54 | ||
47 | { | 55 | { |
48 | const username = 'user2' | 56 | const username = 'user2' |
49 | const password = 'my super password' | 57 | const password = 'my super password' |
50 | await createUser(server.url, server.accessToken, username, password) | 58 | await createUser(servers[0].url, servers[0].accessToken, username, password) |
51 | userAccessToken2 = await userLogin(server, { username, password }) | 59 | userAccessToken2 = await userLogin(servers[0], { username, password }) |
52 | } | 60 | } |
53 | 61 | ||
54 | { | 62 | { |
55 | const res = await uploadVideo(server.url, userAccessToken1, {}) | 63 | const res = await uploadVideo(servers[0].url, userAccessToken1, {}) |
56 | server.video = res.body.video | 64 | servers[0].video = res.body.video |
57 | } | 65 | } |
58 | 66 | ||
59 | { | 67 | { |
60 | const res = await uploadVideo(server.url, server.accessToken, {}) | 68 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, {}) |
61 | notBlacklistedVideoId = res.body.video.uuid | 69 | notBlacklistedVideoId = res.body.video.uuid |
62 | } | 70 | } |
71 | |||
72 | { | ||
73 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, {}) | ||
74 | remoteVideoUUID = res.body.video.uuid | ||
75 | } | ||
76 | |||
77 | await waitJobs(servers) | ||
63 | }) | 78 | }) |
64 | 79 | ||
65 | describe('When adding a video in blacklist', function () { | 80 | describe('When adding a video in blacklist', function () { |
66 | const basePath = '/api/v1/videos/' | 81 | const basePath = '/api/v1/videos/' |
67 | 82 | ||
68 | it('Should fail with nothing', async function () { | 83 | it('Should fail with nothing', async function () { |
69 | const path = basePath + server.video + '/blacklist' | 84 | const path = basePath + servers[0].video + '/blacklist' |
70 | const fields = {} | 85 | const fields = {} |
71 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 86 | await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) |
72 | }) | 87 | }) |
73 | 88 | ||
74 | it('Should fail with a wrong video', async function () { | 89 | it('Should fail with a wrong video', async function () { |
75 | const wrongPath = '/api/v1/videos/blabla/blacklist' | 90 | const wrongPath = '/api/v1/videos/blabla/blacklist' |
76 | const fields = {} | 91 | const fields = {} |
77 | await makePostBodyRequest({ url: server.url, path: wrongPath, token: server.accessToken, fields }) | 92 | await makePostBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields }) |
78 | }) | 93 | }) |
79 | 94 | ||
80 | it('Should fail with a non authenticated user', async function () { | 95 | it('Should fail with a non authenticated user', async function () { |
81 | const path = basePath + server.video + '/blacklist' | 96 | const path = basePath + servers[0].video + '/blacklist' |
82 | const fields = {} | 97 | const fields = {} |
83 | await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 }) | 98 | await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: 401 }) |
84 | }) | 99 | }) |
85 | 100 | ||
86 | it('Should fail with a non admin user', async function () { | 101 | it('Should fail with a non admin user', async function () { |
87 | const path = basePath + server.video + '/blacklist' | 102 | const path = basePath + servers[0].video + '/blacklist' |
88 | const fields = {} | 103 | const fields = {} |
89 | await makePostBodyRequest({ url: server.url, path, token: userAccessToken2, fields, statusCodeExpected: 403 }) | 104 | await makePostBodyRequest({ url: servers[0].url, path, token: userAccessToken2, fields, statusCodeExpected: 403 }) |
90 | }) | 105 | }) |
91 | 106 | ||
92 | it('Should fail with an invalid reason', async function () { | 107 | it('Should fail with an invalid reason', async function () { |
93 | const path = basePath + server.video.uuid + '/blacklist' | 108 | const path = basePath + servers[0].video.uuid + '/blacklist' |
94 | const fields = { reason: 'a'.repeat(305) } | 109 | const fields = { reason: 'a'.repeat(305) } |
95 | 110 | ||
96 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 111 | await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) |
112 | }) | ||
113 | |||
114 | it('Should fail to unfederate a remote video', async function () { | ||
115 | const path = basePath + remoteVideoUUID + '/blacklist' | ||
116 | const fields = { unfederate: true } | ||
117 | |||
118 | await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 409 }) | ||
97 | }) | 119 | }) |
98 | 120 | ||
99 | it('Should succeed with the correct params', async function () { | 121 | it('Should succeed with the correct params', async function () { |
100 | const path = basePath + server.video.uuid + '/blacklist' | 122 | const path = basePath + servers[0].video.uuid + '/blacklist' |
101 | const fields = { } | 123 | const fields = { } |
102 | 124 | ||
103 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 }) | 125 | await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 204 }) |
104 | }) | 126 | }) |
105 | }) | 127 | }) |
106 | 128 | ||
@@ -110,61 +132,61 @@ describe('Test video blacklist API validators', function () { | |||
110 | it('Should fail with a wrong video', async function () { | 132 | it('Should fail with a wrong video', async function () { |
111 | const wrongPath = '/api/v1/videos/blabla/blacklist' | 133 | const wrongPath = '/api/v1/videos/blabla/blacklist' |
112 | const fields = {} | 134 | const fields = {} |
113 | await makePutBodyRequest({ url: server.url, path: wrongPath, token: server.accessToken, fields }) | 135 | await makePutBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields }) |
114 | }) | 136 | }) |
115 | 137 | ||
116 | it('Should fail with a video not blacklisted', async function () { | 138 | it('Should fail with a video not blacklisted', async function () { |
117 | const path = '/api/v1/videos/' + notBlacklistedVideoId + '/blacklist' | 139 | const path = '/api/v1/videos/' + notBlacklistedVideoId + '/blacklist' |
118 | const fields = {} | 140 | const fields = {} |
119 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 404 }) | 141 | await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 404 }) |
120 | }) | 142 | }) |
121 | 143 | ||
122 | it('Should fail with a non authenticated user', async function () { | 144 | it('Should fail with a non authenticated user', async function () { |
123 | const path = basePath + server.video + '/blacklist' | 145 | const path = basePath + servers[0].video + '/blacklist' |
124 | const fields = {} | 146 | const fields = {} |
125 | await makePutBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 }) | 147 | await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, statusCodeExpected: 401 }) |
126 | }) | 148 | }) |
127 | 149 | ||
128 | it('Should fail with a non admin user', async function () { | 150 | it('Should fail with a non admin user', async function () { |
129 | const path = basePath + server.video + '/blacklist' | 151 | const path = basePath + servers[0].video + '/blacklist' |
130 | const fields = {} | 152 | const fields = {} |
131 | await makePutBodyRequest({ url: server.url, path, token: userAccessToken2, fields, statusCodeExpected: 403 }) | 153 | await makePutBodyRequest({ url: servers[0].url, path, token: userAccessToken2, fields, statusCodeExpected: 403 }) |
132 | }) | 154 | }) |
133 | 155 | ||
134 | it('Should fail with an invalid reason', async function () { | 156 | it('Should fail with an invalid reason', async function () { |
135 | const path = basePath + server.video.uuid + '/blacklist' | 157 | const path = basePath + servers[0].video.uuid + '/blacklist' |
136 | const fields = { reason: 'a'.repeat(305) } | 158 | const fields = { reason: 'a'.repeat(305) } |
137 | 159 | ||
138 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 160 | await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields }) |
139 | }) | 161 | }) |
140 | 162 | ||
141 | it('Should succeed with the correct params', async function () { | 163 | it('Should succeed with the correct params', async function () { |
142 | const path = basePath + server.video.uuid + '/blacklist' | 164 | const path = basePath + servers[0].video.uuid + '/blacklist' |
143 | const fields = { reason: 'hello' } | 165 | const fields = { reason: 'hello' } |
144 | 166 | ||
145 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 }) | 167 | await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields, statusCodeExpected: 204 }) |
146 | }) | 168 | }) |
147 | }) | 169 | }) |
148 | 170 | ||
149 | describe('When getting blacklisted video', function () { | 171 | describe('When getting blacklisted video', function () { |
150 | 172 | ||
151 | it('Should fail with a non authenticated user', async function () { | 173 | it('Should fail with a non authenticated user', async function () { |
152 | await getVideo(server.url, server.video.uuid, 401) | 174 | await getVideo(servers[0].url, servers[0].video.uuid, 401) |
153 | }) | 175 | }) |
154 | 176 | ||
155 | it('Should fail with another user', async function () { | 177 | it('Should fail with another user', async function () { |
156 | await getVideoWithToken(server.url, userAccessToken2, server.video.uuid, 403) | 178 | await getVideoWithToken(servers[0].url, userAccessToken2, servers[0].video.uuid, 403) |
157 | }) | 179 | }) |
158 | 180 | ||
159 | it('Should succeed with the owner authenticated user', async function () { | 181 | it('Should succeed with the owner authenticated user', async function () { |
160 | const res = await getVideoWithToken(server.url, userAccessToken1, server.video.uuid, 200) | 182 | const res = await getVideoWithToken(servers[0].url, userAccessToken1, servers[0].video.uuid, 200) |
161 | const video: VideoDetails = res.body | 183 | const video: VideoDetails = res.body |
162 | 184 | ||
163 | expect(video.blacklisted).to.be.true | 185 | expect(video.blacklisted).to.be.true |
164 | }) | 186 | }) |
165 | 187 | ||
166 | it('Should succeed with an admin', async function () { | 188 | it('Should succeed with an admin', async function () { |
167 | const res = await getVideoWithToken(server.url, server.accessToken, server.video.uuid, 200) | 189 | const res = await getVideoWithToken(servers[0].url, servers[0].accessToken, servers[0].video.uuid, 200) |
168 | const video: VideoDetails = res.body | 190 | const video: VideoDetails = res.body |
169 | 191 | ||
170 | expect(video.blacklisted).to.be.true | 192 | expect(video.blacklisted).to.be.true |
@@ -173,24 +195,24 @@ describe('Test video blacklist API validators', function () { | |||
173 | 195 | ||
174 | describe('When removing a video in blacklist', function () { | 196 | describe('When removing a video in blacklist', function () { |
175 | it('Should fail with a non authenticated user', async function () { | 197 | it('Should fail with a non authenticated user', async function () { |
176 | await removeVideoFromBlacklist(server.url, 'fake token', server.video.uuid, 401) | 198 | await removeVideoFromBlacklist(servers[0].url, 'fake token', servers[0].video.uuid, 401) |
177 | }) | 199 | }) |
178 | 200 | ||
179 | it('Should fail with a non admin user', async function () { | 201 | it('Should fail with a non admin user', async function () { |
180 | await removeVideoFromBlacklist(server.url, userAccessToken2, server.video.uuid, 403) | 202 | await removeVideoFromBlacklist(servers[0].url, userAccessToken2, servers[0].video.uuid, 403) |
181 | }) | 203 | }) |
182 | 204 | ||
183 | it('Should fail with an incorrect id', async function () { | 205 | it('Should fail with an incorrect id', async function () { |
184 | await removeVideoFromBlacklist(server.url, server.accessToken, 'hello', 400) | 206 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, 'hello', 400) |
185 | }) | 207 | }) |
186 | 208 | ||
187 | it('Should fail with a not blacklisted video', async function () { | 209 | it('Should fail with a not blacklisted video', async function () { |
188 | // The video was not added to the blacklist so it should fail | 210 | // The video was not added to the blacklist so it should fail |
189 | await removeVideoFromBlacklist(server.url, server.accessToken, notBlacklistedVideoId, 404) | 211 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, notBlacklistedVideoId, 404) |
190 | }) | 212 | }) |
191 | 213 | ||
192 | it('Should succeed with the correct params', async function () { | 214 | it('Should succeed with the correct params', async function () { |
193 | await removeVideoFromBlacklist(server.url, server.accessToken, server.video.uuid, 204) | 215 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, servers[0].video.uuid, 204) |
194 | }) | 216 | }) |
195 | }) | 217 | }) |
196 | 218 | ||
@@ -198,28 +220,28 @@ describe('Test video blacklist API validators', function () { | |||
198 | const basePath = '/api/v1/videos/blacklist/' | 220 | const basePath = '/api/v1/videos/blacklist/' |
199 | 221 | ||
200 | it('Should fail with a non authenticated user', async function () { | 222 | it('Should fail with a non authenticated user', async function () { |
201 | await getBlacklistedVideosList(server.url, 'fake token', 401) | 223 | await getBlacklistedVideosList(servers[0].url, 'fake token', 401) |
202 | }) | 224 | }) |
203 | 225 | ||
204 | it('Should fail with a non admin user', async function () { | 226 | it('Should fail with a non admin user', async function () { |
205 | await getBlacklistedVideosList(server.url, userAccessToken2, 403) | 227 | await getBlacklistedVideosList(servers[0].url, userAccessToken2, 403) |
206 | }) | 228 | }) |
207 | 229 | ||
208 | it('Should fail with a bad start pagination', async function () { | 230 | it('Should fail with a bad start pagination', async function () { |
209 | await checkBadStartPagination(server.url, basePath, server.accessToken) | 231 | await checkBadStartPagination(servers[0].url, basePath, servers[0].accessToken) |
210 | }) | 232 | }) |
211 | 233 | ||
212 | it('Should fail with a bad count pagination', async function () { | 234 | it('Should fail with a bad count pagination', async function () { |
213 | await checkBadCountPagination(server.url, basePath, server.accessToken) | 235 | await checkBadCountPagination(servers[0].url, basePath, servers[0].accessToken) |
214 | }) | 236 | }) |
215 | 237 | ||
216 | it('Should fail with an incorrect sort', async function () { | 238 | it('Should fail with an incorrect sort', async function () { |
217 | await checkBadSortPagination(server.url, basePath, server.accessToken) | 239 | await checkBadSortPagination(servers[0].url, basePath, servers[0].accessToken) |
218 | }) | 240 | }) |
219 | }) | 241 | }) |
220 | 242 | ||
221 | after(async function () { | 243 | after(async function () { |
222 | killallServers([ server ]) | 244 | killallServers(servers) |
223 | 245 | ||
224 | // Keep the logs if the test failed | 246 | // Keep the logs if the test failed |
225 | if (this['ok']) { | 247 | if (this['ok']) { |
diff --git a/server/tests/api/check-params/video-captions.ts b/server/tests/api/check-params/video-captions.ts index 8d46971a1..e4d36fd4f 100644 --- a/server/tests/api/check-params/video-captions.ts +++ b/server/tests/api/check-params/video-captions.ts | |||
@@ -13,9 +13,9 @@ import { | |||
13 | setAccessTokensToServers, | 13 | setAccessTokensToServers, |
14 | uploadVideo, | 14 | uploadVideo, |
15 | userLogin | 15 | userLogin |
16 | } from '../../utils' | 16 | } from '../../../../shared/utils' |
17 | import { join } from 'path' | 17 | import { join } from 'path' |
18 | import { createVideoCaption } from '../../utils/videos/video-captions' | 18 | import { createVideoCaption } from '../../../../shared/utils/videos/video-captions' |
19 | 19 | ||
20 | describe('Test video captions API validator', function () { | 20 | describe('Test video captions API validator', function () { |
21 | const path = '/api/v1/videos/' | 21 | const path = '/api/v1/videos/' |
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index 3a7942945..14e4deaf7 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -20,8 +20,12 @@ import { | |||
20 | ServerInfo, | 20 | ServerInfo, |
21 | setAccessTokensToServers, | 21 | setAccessTokensToServers, |
22 | userLogin | 22 | userLogin |
23 | } from '../../utils' | 23 | } from '../../../../shared/utils' |
24 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 24 | import { |
25 | checkBadCountPagination, | ||
26 | checkBadSortPagination, | ||
27 | checkBadStartPagination | ||
28 | } from '../../../../shared/utils/requests/check-api-params' | ||
25 | import { User } from '../../../../shared/models/users' | 29 | import { User } from '../../../../shared/models/users' |
26 | import { join } from 'path' | 30 | import { join } from 'path' |
27 | 31 | ||
@@ -118,12 +122,12 @@ describe('Test video channels API validator', function () { | |||
118 | }) | 122 | }) |
119 | 123 | ||
120 | it('Should fail with a long description', async function () { | 124 | it('Should fail with a long description', async function () { |
121 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(150) }) | 125 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) }) |
122 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | 126 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) |
123 | }) | 127 | }) |
124 | 128 | ||
125 | it('Should fail with a long support text', async function () { | 129 | it('Should fail with a long support text', async function () { |
126 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 130 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
127 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | 131 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) |
128 | }) | 132 | }) |
129 | 133 | ||
@@ -185,12 +189,12 @@ describe('Test video channels API validator', function () { | |||
185 | }) | 189 | }) |
186 | 190 | ||
187 | it('Should fail with a long description', async function () { | 191 | it('Should fail with a long description', async function () { |
188 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(150) }) | 192 | const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(201) }) |
189 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 193 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
190 | }) | 194 | }) |
191 | 195 | ||
192 | it('Should fail with a long support text', async function () { | 196 | it('Should fail with a long support text', async function () { |
193 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 197 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
194 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 198 | await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
195 | }) | 199 | }) |
196 | 200 | ||
diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts index 5241832fe..5981780ed 100644 --- a/server/tests/api/check-params/video-comments.ts +++ b/server/tests/api/check-params/video-comments.ts | |||
@@ -6,9 +6,13 @@ import { | |||
6 | createUser, | 6 | createUser, |
7 | flushTests, killallServers, makeDeleteRequest, makeGetRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, | 7 | flushTests, killallServers, makeDeleteRequest, makeGetRequest, makePostBodyRequest, runServer, ServerInfo, setAccessTokensToServers, |
8 | uploadVideo, userLogin | 8 | uploadVideo, userLogin |
9 | } from '../../utils' | 9 | } from '../../../../shared/utils' |
10 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 10 | import { |
11 | import { addVideoCommentThread } from '../../utils/videos/video-comments' | 11 | checkBadCountPagination, |
12 | checkBadSortPagination, | ||
13 | checkBadStartPagination | ||
14 | } from '../../../../shared/utils/requests/check-api-params' | ||
15 | import { addVideoCommentThread } from '../../../../shared/utils/videos/video-comments' | ||
12 | 16 | ||
13 | const expect = chai.expect | 17 | const expect = chai.expect |
14 | 18 | ||
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts index 1ffb81a38..6dd9f15f7 100644 --- a/server/tests/api/check-params/video-imports.ts +++ b/server/tests/api/check-params/video-imports.ts | |||
@@ -18,9 +18,13 @@ import { | |||
18 | setAccessTokensToServers, | 18 | setAccessTokensToServers, |
19 | updateCustomSubConfig, | 19 | updateCustomSubConfig, |
20 | userLogin | 20 | userLogin |
21 | } from '../../utils' | 21 | } from '../../../../shared/utils' |
22 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 22 | import { |
23 | import { getMagnetURI, getYoutubeVideoUrl } from '../../utils/videos/video-imports' | 23 | checkBadCountPagination, |
24 | checkBadSortPagination, | ||
25 | checkBadStartPagination | ||
26 | } from '../../../../shared/utils/requests/check-api-params' | ||
27 | import { getMagnetURI, getYoutubeVideoUrl } from '../../../../shared/utils/videos/video-imports' | ||
24 | 28 | ||
25 | describe('Test video imports API validator', function () { | 29 | describe('Test video imports API validator', function () { |
26 | const path = '/api/v1/videos/imports' | 30 | const path = '/api/v1/videos/imports' |
@@ -141,7 +145,7 @@ describe('Test video imports API validator', function () { | |||
141 | }) | 145 | }) |
142 | 146 | ||
143 | it('Should fail with a long support text', async function () { | 147 | it('Should fail with a long support text', async function () { |
144 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 148 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
145 | 149 | ||
146 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | 150 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) |
147 | }) | 151 | }) |
diff --git a/server/tests/api/check-params/videos-filter.ts b/server/tests/api/check-params/videos-filter.ts new file mode 100644 index 000000000..e998c8a3d --- /dev/null +++ b/server/tests/api/check-params/videos-filter.ts | |||
@@ -0,0 +1,127 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | createUser, | ||
7 | flushTests, | ||
8 | killallServers, | ||
9 | makeGetRequest, | ||
10 | runServer, | ||
11 | ServerInfo, | ||
12 | setAccessTokensToServers, | ||
13 | userLogin | ||
14 | } from '../../../../shared/utils' | ||
15 | import { UserRole } from '../../../../shared/models/users' | ||
16 | |||
17 | const expect = chai.expect | ||
18 | |||
19 | async function testEndpoints (server: ServerInfo, token: string, filter: string, statusCodeExpected: number) { | ||
20 | const paths = [ | ||
21 | '/api/v1/video-channels/root_channel/videos', | ||
22 | '/api/v1/accounts/root/videos', | ||
23 | '/api/v1/videos', | ||
24 | '/api/v1/search/videos' | ||
25 | ] | ||
26 | |||
27 | for (const path of paths) { | ||
28 | await makeGetRequest({ | ||
29 | url: server.url, | ||
30 | path, | ||
31 | token, | ||
32 | query: { | ||
33 | filter | ||
34 | }, | ||
35 | statusCodeExpected | ||
36 | }) | ||
37 | } | ||
38 | } | ||
39 | |||
40 | describe('Test videos filters', function () { | ||
41 | let server: ServerInfo | ||
42 | let userAccessToken: string | ||
43 | let moderatorAccessToken: string | ||
44 | |||
45 | // --------------------------------------------------------------- | ||
46 | |||
47 | before(async function () { | ||
48 | this.timeout(30000) | ||
49 | |||
50 | await flushTests() | ||
51 | |||
52 | server = await runServer(1) | ||
53 | |||
54 | await setAccessTokensToServers([ server ]) | ||
55 | |||
56 | const user = { username: 'user1', password: 'my super password' } | ||
57 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
58 | userAccessToken = await userLogin(server, user) | ||
59 | |||
60 | const moderator = { username: 'moderator', password: 'my super password' } | ||
61 | await createUser( | ||
62 | server.url, | ||
63 | server.accessToken, | ||
64 | moderator.username, | ||
65 | moderator.password, | ||
66 | undefined, | ||
67 | undefined, | ||
68 | UserRole.MODERATOR | ||
69 | ) | ||
70 | moderatorAccessToken = await userLogin(server, moderator) | ||
71 | }) | ||
72 | |||
73 | describe('When setting a video filter', function () { | ||
74 | |||
75 | it('Should fail with a bad filter', async function () { | ||
76 | await testEndpoints(server, server.accessToken, 'bad-filter', 400) | ||
77 | }) | ||
78 | |||
79 | it('Should succeed with a good filter', async function () { | ||
80 | await testEndpoints(server, server.accessToken,'local', 200) | ||
81 | }) | ||
82 | |||
83 | it('Should fail to list all-local with a simple user', async function () { | ||
84 | await testEndpoints(server, userAccessToken, 'all-local', 401) | ||
85 | }) | ||
86 | |||
87 | it('Should succeed to list all-local with a moderator', async function () { | ||
88 | await testEndpoints(server, moderatorAccessToken, 'all-local', 200) | ||
89 | }) | ||
90 | |||
91 | it('Should succeed to list all-local with an admin', async function () { | ||
92 | await testEndpoints(server, server.accessToken, 'all-local', 200) | ||
93 | }) | ||
94 | |||
95 | // Because we cannot authenticate the user on the RSS endpoint | ||
96 | it('Should fail on the feeds endpoint with the all-local filter', async function () { | ||
97 | await makeGetRequest({ | ||
98 | url: server.url, | ||
99 | path: '/feeds/videos.json', | ||
100 | statusCodeExpected: 401, | ||
101 | query: { | ||
102 | filter: 'all-local' | ||
103 | } | ||
104 | }) | ||
105 | }) | ||
106 | |||
107 | it('Should succed on the feeds endpoint with the local filter', async function () { | ||
108 | await makeGetRequest({ | ||
109 | url: server.url, | ||
110 | path: '/feeds/videos.json', | ||
111 | statusCodeExpected: 200, | ||
112 | query: { | ||
113 | filter: 'local' | ||
114 | } | ||
115 | }) | ||
116 | }) | ||
117 | }) | ||
118 | |||
119 | after(async function () { | ||
120 | killallServers([ server ]) | ||
121 | |||
122 | // Keep the logs if the test failed | ||
123 | if (this['ok']) { | ||
124 | await flushTests() | ||
125 | } | ||
126 | }) | ||
127 | }) | ||
diff --git a/server/tests/api/check-params/videos-history.ts b/server/tests/api/check-params/videos-history.ts index 808c3b616..8c079a956 100644 --- a/server/tests/api/check-params/videos-history.ts +++ b/server/tests/api/check-params/videos-history.ts | |||
@@ -3,20 +3,25 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { | 5 | import { |
6 | checkBadCountPagination, | ||
7 | checkBadStartPagination, | ||
6 | flushTests, | 8 | flushTests, |
7 | killallServers, | 9 | killallServers, |
10 | makeGetRequest, | ||
8 | makePostBodyRequest, | 11 | makePostBodyRequest, |
9 | makePutBodyRequest, | 12 | makePutBodyRequest, |
10 | runServer, | 13 | runServer, |
11 | ServerInfo, | 14 | ServerInfo, |
12 | setAccessTokensToServers, | 15 | setAccessTokensToServers, |
13 | uploadVideo | 16 | uploadVideo |
14 | } from '../../utils' | 17 | } from '../../../../shared/utils' |
15 | 18 | ||
16 | const expect = chai.expect | 19 | const expect = chai.expect |
17 | 20 | ||
18 | describe('Test videos history API validator', function () { | 21 | describe('Test videos history API validator', function () { |
19 | let path: string | 22 | let watchingPath: string |
23 | let myHistoryPath = '/api/v1/users/me/history/videos' | ||
24 | let myHistoryRemove = myHistoryPath + '/remove' | ||
20 | let server: ServerInfo | 25 | let server: ServerInfo |
21 | 26 | ||
22 | // --------------------------------------------------------------- | 27 | // --------------------------------------------------------------- |
@@ -33,14 +38,14 @@ describe('Test videos history API validator', function () { | |||
33 | const res = await uploadVideo(server.url, server.accessToken, {}) | 38 | const res = await uploadVideo(server.url, server.accessToken, {}) |
34 | const videoUUID = res.body.video.uuid | 39 | const videoUUID = res.body.video.uuid |
35 | 40 | ||
36 | path = '/api/v1/videos/' + videoUUID + '/watching' | 41 | watchingPath = '/api/v1/videos/' + videoUUID + '/watching' |
37 | }) | 42 | }) |
38 | 43 | ||
39 | describe('When notifying a user is watching a video', function () { | 44 | describe('When notifying a user is watching a video', function () { |
40 | 45 | ||
41 | it('Should fail with an unauthenticated user', async function () { | 46 | it('Should fail with an unauthenticated user', async function () { |
42 | const fields = { currentTime: 5 } | 47 | const fields = { currentTime: 5 } |
43 | await makePutBodyRequest({ url: server.url, path, fields, statusCodeExpected: 401 }) | 48 | await makePutBodyRequest({ url: server.url, path: watchingPath, fields, statusCodeExpected: 401 }) |
44 | }) | 49 | }) |
45 | 50 | ||
46 | it('Should fail with an incorrect video id', async function () { | 51 | it('Should fail with an incorrect video id', async function () { |
@@ -58,13 +63,68 @@ describe('Test videos history API validator', function () { | |||
58 | 63 | ||
59 | it('Should fail with a bad current time', async function () { | 64 | it('Should fail with a bad current time', async function () { |
60 | const fields = { currentTime: 'hello' } | 65 | const fields = { currentTime: 'hello' } |
61 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 400 }) | 66 | await makePutBodyRequest({ url: server.url, path: watchingPath, fields, token: server.accessToken, statusCodeExpected: 400 }) |
62 | }) | 67 | }) |
63 | 68 | ||
64 | it('Should succeed with the correct parameters', async function () { | 69 | it('Should succeed with the correct parameters', async function () { |
65 | const fields = { currentTime: 5 } | 70 | const fields = { currentTime: 5 } |
66 | 71 | ||
67 | await makePutBodyRequest({ url: server.url, path, fields, token: server.accessToken, statusCodeExpected: 204 }) | 72 | await makePutBodyRequest({ url: server.url, path: watchingPath, fields, token: server.accessToken, statusCodeExpected: 204 }) |
73 | }) | ||
74 | }) | ||
75 | |||
76 | describe('When listing user videos history', function () { | ||
77 | it('Should fail with a bad start pagination', async function () { | ||
78 | await checkBadStartPagination(server.url, myHistoryPath, server.accessToken) | ||
79 | }) | ||
80 | |||
81 | it('Should fail with a bad count pagination', async function () { | ||
82 | await checkBadCountPagination(server.url, myHistoryPath, server.accessToken) | ||
83 | }) | ||
84 | |||
85 | it('Should fail with an unauthenticated user', async function () { | ||
86 | await makeGetRequest({ url: server.url, path: myHistoryPath, statusCodeExpected: 401 }) | ||
87 | }) | ||
88 | |||
89 | it('Should succeed with the correct params', async function () { | ||
90 | await makeGetRequest({ url: server.url, token: server.accessToken, path: myHistoryPath, statusCodeExpected: 200 }) | ||
91 | }) | ||
92 | }) | ||
93 | |||
94 | describe('When removing user videos history', function () { | ||
95 | it('Should fail with an unauthenticated user', async function () { | ||
96 | await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', statusCodeExpected: 401 }) | ||
97 | }) | ||
98 | |||
99 | it('Should fail with a bad beforeDate parameter', async function () { | ||
100 | const body = { beforeDate: '15' } | ||
101 | await makePostBodyRequest({ | ||
102 | url: server.url, | ||
103 | token: server.accessToken, | ||
104 | path: myHistoryRemove, | ||
105 | fields: body, | ||
106 | statusCodeExpected: 400 | ||
107 | }) | ||
108 | }) | ||
109 | |||
110 | it('Should succeed with a valid beforeDate param', async function () { | ||
111 | const body = { beforeDate: new Date().toISOString() } | ||
112 | await makePostBodyRequest({ | ||
113 | url: server.url, | ||
114 | token: server.accessToken, | ||
115 | path: myHistoryRemove, | ||
116 | fields: body, | ||
117 | statusCodeExpected: 204 | ||
118 | }) | ||
119 | }) | ||
120 | |||
121 | it('Should succeed without body', async function () { | ||
122 | await makePostBodyRequest({ | ||
123 | url: server.url, | ||
124 | token: server.accessToken, | ||
125 | path: myHistoryRemove, | ||
126 | statusCodeExpected: 204 | ||
127 | }) | ||
68 | }) | 128 | }) |
69 | }) | 129 | }) |
70 | 130 | ||
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index bc28e2422..878ffe025 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts | |||
@@ -8,9 +8,13 @@ import { VideoPrivacy } from '../../../../shared/models/videos/video-privacy.enu | |||
8 | import { | 8 | import { |
9 | createUser, flushTests, getMyUserInformation, getVideo, getVideosList, immutableAssign, killallServers, makeDeleteRequest, | 9 | createUser, flushTests, getMyUserInformation, getVideo, getVideosList, immutableAssign, killallServers, makeDeleteRequest, |
10 | makeGetRequest, makeUploadRequest, makePutBodyRequest, removeVideo, runServer, ServerInfo, setAccessTokensToServers, userLogin | 10 | makeGetRequest, makeUploadRequest, makePutBodyRequest, removeVideo, runServer, ServerInfo, setAccessTokensToServers, userLogin |
11 | } from '../../utils' | 11 | } from '../../../../shared/utils' |
12 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params' | 12 | import { |
13 | import { getAccountsList } from '../../utils/users/accounts' | 13 | checkBadCountPagination, |
14 | checkBadSortPagination, | ||
15 | checkBadStartPagination | ||
16 | } from '../../../../shared/utils/requests/check-api-params' | ||
17 | import { getAccountsList } from '../../../../shared/utils/users/accounts' | ||
14 | 18 | ||
15 | const expect = chai.expect | 19 | const expect = chai.expect |
16 | 20 | ||
@@ -234,7 +238,7 @@ describe('Test videos API validator', function () { | |||
234 | }) | 238 | }) |
235 | 239 | ||
236 | it('Should fail with a long support text', async function () { | 240 | it('Should fail with a long support text', async function () { |
237 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 241 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
238 | const attaches = baseCorrectAttaches | 242 | const attaches = baseCorrectAttaches |
239 | 243 | ||
240 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 244 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
@@ -317,10 +321,15 @@ describe('Test videos API validator', function () { | |||
317 | 321 | ||
318 | it('Should fail without an incorrect input file', async function () { | 322 | it('Should fail without an incorrect input file', async function () { |
319 | const fields = baseCorrectParams | 323 | const fields = baseCorrectParams |
320 | const attaches = { | 324 | let attaches = { |
321 | 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') | 325 | 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short_fake.webm') |
322 | } | 326 | } |
323 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | 327 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) |
328 | |||
329 | attaches = { | ||
330 | 'videofile': join(__dirname, '..', '..', 'fixtures', 'video_short.mkv') | ||
331 | } | ||
332 | await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) | ||
324 | }) | 333 | }) |
325 | 334 | ||
326 | it('Should fail with an incorrect thumbnail file', async function () { | 335 | it('Should fail with an incorrect thumbnail file', async function () { |
@@ -484,7 +493,7 @@ describe('Test videos API validator', function () { | |||
484 | }) | 493 | }) |
485 | 494 | ||
486 | it('Should fail with a long support text', async function () { | 495 | it('Should fail with a long support text', async function () { |
487 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(150) }) | 496 | const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(201) }) |
488 | 497 | ||
489 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) | 498 | await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) |
490 | }) | 499 | }) |
diff --git a/server/tests/api/index-4.ts b/server/tests/api/index-4.ts new file mode 100644 index 000000000..7d8be2b3d --- /dev/null +++ b/server/tests/api/index-4.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | import './redundancy' | ||
2 | import './activitypub' | ||
diff --git a/server/tests/api/index.ts b/server/tests/api/index.ts index 2d996dbf9..bc140f860 100644 --- a/server/tests/api/index.ts +++ b/server/tests/api/index.ts | |||
@@ -2,3 +2,4 @@ | |||
2 | import './index-1' | 2 | import './index-1' |
3 | import './index-2' | 3 | import './index-2' |
4 | import './index-3' | 4 | import './index-3' |
5 | import './index-4' | ||
diff --git a/server/tests/api/redundancy/index.ts b/server/tests/api/redundancy/index.ts new file mode 100644 index 000000000..8e69b95a6 --- /dev/null +++ b/server/tests/api/redundancy/index.ts | |||
@@ -0,0 +1 @@ | |||
import './redundancy' | |||
diff --git a/server/tests/api/server/redundancy.ts b/server/tests/api/redundancy/redundancy.ts index 1960854b6..778611fff 100644 --- a/server/tests/api/server/redundancy.ts +++ b/server/tests/api/redundancy/redundancy.ts | |||
@@ -17,16 +17,17 @@ import { | |||
17 | viewVideo, | 17 | viewVideo, |
18 | wait, | 18 | wait, |
19 | waitUntilLog, | 19 | waitUntilLog, |
20 | checkVideoFilesWereRemoved, removeVideo | 20 | checkVideoFilesWereRemoved, removeVideo, getVideoWithToken, reRunServer, checkSegmentHash |
21 | } from '../../utils' | 21 | } from '../../../../shared/utils' |
22 | import { waitJobs } from '../../utils/server/jobs' | 22 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
23 | |||
23 | import * as magnetUtil from 'magnet-uri' | 24 | import * as magnetUtil from 'magnet-uri' |
24 | import { updateRedundancy } from '../../utils/server/redundancy' | 25 | import { updateRedundancy } from '../../../../shared/utils/server/redundancy' |
25 | import { ActorFollow } from '../../../../shared/models/actors' | 26 | import { ActorFollow } from '../../../../shared/models/actors' |
26 | import { readdir } from 'fs-extra' | 27 | import { readdir } from 'fs-extra' |
27 | import { join } from 'path' | 28 | import { join } from 'path' |
28 | import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy' | 29 | import { VideoRedundancyStrategy } from '../../../../shared/models/redundancy' |
29 | import { getStats } from '../../utils/server/stats' | 30 | import { getStats } from '../../../../shared/utils/server/stats' |
30 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' | 31 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' |
31 | 32 | ||
32 | const expect = chai.expect | 33 | const expect = chai.expect |
@@ -47,6 +48,11 @@ function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: numbe | |||
47 | 48 | ||
48 | async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) { | 49 | async function runServers (strategy: VideoRedundancyStrategy, additionalParams: any = {}) { |
49 | const config = { | 50 | const config = { |
51 | transcoding: { | ||
52 | hls: { | ||
53 | enabled: true | ||
54 | } | ||
55 | }, | ||
50 | redundancy: { | 56 | redundancy: { |
51 | videos: { | 57 | videos: { |
52 | check_interval: '5 seconds', | 58 | check_interval: '5 seconds', |
@@ -54,7 +60,7 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: | |||
54 | immutableAssign({ | 60 | immutableAssign({ |
55 | min_lifetime: '1 hour', | 61 | min_lifetime: '1 hour', |
56 | strategy: strategy, | 62 | strategy: strategy, |
57 | size: '100KB' | 63 | size: '200KB' |
58 | }, additionalParams) | 64 | }, additionalParams) |
59 | ] | 65 | ] |
60 | } | 66 | } |
@@ -84,7 +90,7 @@ async function runServers (strategy: VideoRedundancyStrategy, additionalParams: | |||
84 | await waitJobs(servers) | 90 | await waitJobs(servers) |
85 | } | 91 | } |
86 | 92 | ||
87 | async function check1WebSeed (strategy: VideoRedundancyStrategy, videoUUID?: string) { | 93 | async function check1WebSeed (videoUUID?: string) { |
88 | if (!videoUUID) videoUUID = video1Server2UUID | 94 | if (!videoUUID) videoUUID = video1Server2UUID |
89 | 95 | ||
90 | const webseeds = [ | 96 | const webseeds = [ |
@@ -92,50 +98,21 @@ async function check1WebSeed (strategy: VideoRedundancyStrategy, videoUUID?: str | |||
92 | ] | 98 | ] |
93 | 99 | ||
94 | for (const server of servers) { | 100 | for (const server of servers) { |
95 | { | 101 | // With token to avoid issues with video follow constraints |
96 | const res = await getVideo(server.url, videoUUID) | 102 | const res = await getVideoWithToken(server.url, server.accessToken, videoUUID) |
97 | 103 | ||
98 | const video: VideoDetails = res.body | 104 | const video: VideoDetails = res.body |
99 | for (const f of video.files) { | 105 | for (const f of video.files) { |
100 | checkMagnetWebseeds(f, webseeds, server) | 106 | checkMagnetWebseeds(f, webseeds, server) |
101 | } | ||
102 | } | 107 | } |
103 | } | 108 | } |
104 | } | 109 | } |
105 | 110 | ||
106 | async function checkStatsWith2Webseed (strategy: VideoRedundancyStrategy) { | 111 | async function check2Webseeds (videoUUID?: string) { |
107 | const res = await getStats(servers[0].url) | ||
108 | const data: ServerStats = res.body | ||
109 | |||
110 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
111 | const stat = data.videosRedundancy[0] | ||
112 | |||
113 | expect(stat.strategy).to.equal(strategy) | ||
114 | expect(stat.totalSize).to.equal(102400) | ||
115 | expect(stat.totalUsed).to.be.at.least(1).and.below(102401) | ||
116 | expect(stat.totalVideoFiles).to.equal(4) | ||
117 | expect(stat.totalVideos).to.equal(1) | ||
118 | } | ||
119 | |||
120 | async function checkStatsWith1Webseed (strategy: VideoRedundancyStrategy) { | ||
121 | const res = await getStats(servers[0].url) | ||
122 | const data: ServerStats = res.body | ||
123 | |||
124 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
125 | |||
126 | const stat = data.videosRedundancy[0] | ||
127 | expect(stat.strategy).to.equal(strategy) | ||
128 | expect(stat.totalSize).to.equal(102400) | ||
129 | expect(stat.totalUsed).to.equal(0) | ||
130 | expect(stat.totalVideoFiles).to.equal(0) | ||
131 | expect(stat.totalVideos).to.equal(0) | ||
132 | } | ||
133 | |||
134 | async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: string) { | ||
135 | if (!videoUUID) videoUUID = video1Server2UUID | 112 | if (!videoUUID) videoUUID = video1Server2UUID |
136 | 113 | ||
137 | const webseeds = [ | 114 | const webseeds = [ |
138 | 'http://localhost:9001/static/webseed/' + videoUUID, | 115 | 'http://localhost:9001/static/redundancy/' + videoUUID, |
139 | 'http://localhost:9002/static/webseed/' + videoUUID | 116 | 'http://localhost:9002/static/webseed/' + videoUUID |
140 | ] | 117 | ] |
141 | 118 | ||
@@ -147,20 +124,23 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st | |||
147 | for (const file of video.files) { | 124 | for (const file of video.files) { |
148 | checkMagnetWebseeds(file, webseeds, server) | 125 | checkMagnetWebseeds(file, webseeds, server) |
149 | 126 | ||
150 | // Only servers 1 and 2 have the video | 127 | await makeGetRequest({ |
151 | if (server.serverNumber !== 3) { | 128 | url: servers[0].url, |
152 | await makeGetRequest({ | 129 | statusCodeExpected: 200, |
153 | url: server.url, | 130 | path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`, |
154 | statusCodeExpected: 200, | 131 | contentType: null |
155 | path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, | 132 | }) |
156 | contentType: null | 133 | await makeGetRequest({ |
157 | }) | 134 | url: servers[1].url, |
158 | } | 135 | statusCodeExpected: 200, |
136 | path: `/static/webseed/${videoUUID}-${file.resolution.id}.mp4`, | ||
137 | contentType: null | ||
138 | }) | ||
159 | } | 139 | } |
160 | } | 140 | } |
161 | 141 | ||
162 | for (const directory of [ 'test1', 'test2' ]) { | 142 | for (const directory of [ 'test1/redundancy', 'test2/videos' ]) { |
163 | const files = await readdir(join(root(), directory, 'videos')) | 143 | const files = await readdir(join(root(), directory)) |
164 | expect(files).to.have.length.at.least(4) | 144 | expect(files).to.have.length.at.least(4) |
165 | 145 | ||
166 | for (const resolution of [ 240, 360, 480, 720 ]) { | 146 | for (const resolution of [ 240, 360, 480, 720 ]) { |
@@ -169,6 +149,85 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st | |||
169 | } | 149 | } |
170 | } | 150 | } |
171 | 151 | ||
152 | async function check0PlaylistRedundancies (videoUUID?: string) { | ||
153 | if (!videoUUID) videoUUID = video1Server2UUID | ||
154 | |||
155 | for (const server of servers) { | ||
156 | // With token to avoid issues with video follow constraints | ||
157 | const res = await getVideoWithToken(server.url, server.accessToken, videoUUID) | ||
158 | const video: VideoDetails = res.body | ||
159 | |||
160 | expect(video.streamingPlaylists).to.be.an('array') | ||
161 | expect(video.streamingPlaylists).to.have.lengthOf(1) | ||
162 | expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | async function check1PlaylistRedundancies (videoUUID?: string) { | ||
167 | if (!videoUUID) videoUUID = video1Server2UUID | ||
168 | |||
169 | for (const server of servers) { | ||
170 | const res = await getVideo(server.url, videoUUID) | ||
171 | const video: VideoDetails = res.body | ||
172 | |||
173 | expect(video.streamingPlaylists).to.have.lengthOf(1) | ||
174 | expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(1) | ||
175 | |||
176 | const redundancy = video.streamingPlaylists[0].redundancies[0] | ||
177 | |||
178 | expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID) | ||
179 | } | ||
180 | |||
181 | const baseUrlPlaylist = servers[1].url + '/static/playlists/hls' | ||
182 | const baseUrlSegment = servers[0].url + '/static/redundancy/hls' | ||
183 | |||
184 | const res = await getVideo(servers[0].url, videoUUID) | ||
185 | const hlsPlaylist = (res.body as VideoDetails).streamingPlaylists[0] | ||
186 | |||
187 | for (const resolution of [ 240, 360, 480, 720 ]) { | ||
188 | await checkSegmentHash(baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist) | ||
189 | } | ||
190 | |||
191 | for (const directory of [ 'test1/redundancy/hls', 'test2/playlists/hls' ]) { | ||
192 | const files = await readdir(join(root(), directory, videoUUID)) | ||
193 | expect(files).to.have.length.at.least(4) | ||
194 | |||
195 | for (const resolution of [ 240, 360, 480, 720 ]) { | ||
196 | const filename = `${videoUUID}-${resolution}-fragmented.mp4` | ||
197 | |||
198 | expect(files.find(f => f === filename)).to.not.be.undefined | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | async function checkStatsWith2Webseed (strategy: VideoRedundancyStrategy) { | ||
204 | const res = await getStats(servers[0].url) | ||
205 | const data: ServerStats = res.body | ||
206 | |||
207 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
208 | const stat = data.videosRedundancy[0] | ||
209 | |||
210 | expect(stat.strategy).to.equal(strategy) | ||
211 | expect(stat.totalSize).to.equal(204800) | ||
212 | expect(stat.totalUsed).to.be.at.least(1).and.below(204801) | ||
213 | expect(stat.totalVideoFiles).to.equal(4) | ||
214 | expect(stat.totalVideos).to.equal(1) | ||
215 | } | ||
216 | |||
217 | async function checkStatsWith1Webseed (strategy: VideoRedundancyStrategy) { | ||
218 | const res = await getStats(servers[0].url) | ||
219 | const data: ServerStats = res.body | ||
220 | |||
221 | expect(data.videosRedundancy).to.have.lengthOf(1) | ||
222 | |||
223 | const stat = data.videosRedundancy[0] | ||
224 | expect(stat.strategy).to.equal(strategy) | ||
225 | expect(stat.totalSize).to.equal(204800) | ||
226 | expect(stat.totalUsed).to.equal(0) | ||
227 | expect(stat.totalVideoFiles).to.equal(0) | ||
228 | expect(stat.totalVideos).to.equal(0) | ||
229 | } | ||
230 | |||
172 | async function enableRedundancyOnServer1 () { | 231 | async function enableRedundancyOnServer1 () { |
173 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) | 232 | await updateRedundancy(servers[ 0 ].url, servers[ 0 ].accessToken, servers[ 1 ].host, true) |
174 | 233 | ||
@@ -215,7 +274,8 @@ describe('Test videos redundancy', function () { | |||
215 | }) | 274 | }) |
216 | 275 | ||
217 | it('Should have 1 webseed on the first video', async function () { | 276 | it('Should have 1 webseed on the first video', async function () { |
218 | await check1WebSeed(strategy) | 277 | await check1WebSeed() |
278 | await check0PlaylistRedundancies() | ||
219 | await checkStatsWith1Webseed(strategy) | 279 | await checkStatsWith1Webseed(strategy) |
220 | }) | 280 | }) |
221 | 281 | ||
@@ -223,28 +283,30 @@ describe('Test videos redundancy', function () { | |||
223 | return enableRedundancyOnServer1() | 283 | return enableRedundancyOnServer1() |
224 | }) | 284 | }) |
225 | 285 | ||
226 | it('Should have 2 webseed on the first video', async function () { | 286 | it('Should have 2 webseeds on the first video', async function () { |
227 | this.timeout(40000) | 287 | this.timeout(80000) |
228 | 288 | ||
229 | await waitJobs(servers) | 289 | await waitJobs(servers) |
230 | await waitUntilLog(servers[0], 'Duplicated ', 4) | 290 | await waitUntilLog(servers[0], 'Duplicated ', 5) |
231 | await waitJobs(servers) | 291 | await waitJobs(servers) |
232 | 292 | ||
233 | await check2Webseeds(strategy) | 293 | await check2Webseeds() |
294 | await check1PlaylistRedundancies() | ||
234 | await checkStatsWith2Webseed(strategy) | 295 | await checkStatsWith2Webseed(strategy) |
235 | }) | 296 | }) |
236 | 297 | ||
237 | it('Should undo redundancy on server 1 and remove duplicated videos', async function () { | 298 | it('Should undo redundancy on server 1 and remove duplicated videos', async function () { |
238 | this.timeout(40000) | 299 | this.timeout(80000) |
239 | 300 | ||
240 | await disableRedundancyOnServer1() | 301 | await disableRedundancyOnServer1() |
241 | 302 | ||
242 | await waitJobs(servers) | 303 | await waitJobs(servers) |
243 | await wait(5000) | 304 | await wait(5000) |
244 | 305 | ||
245 | await check1WebSeed(strategy) | 306 | await check1WebSeed() |
307 | await check0PlaylistRedundancies() | ||
246 | 308 | ||
247 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) | 309 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos', join('playlists', 'hls') ]) |
248 | }) | 310 | }) |
249 | 311 | ||
250 | after(function () { | 312 | after(function () { |
@@ -262,7 +324,8 @@ describe('Test videos redundancy', function () { | |||
262 | }) | 324 | }) |
263 | 325 | ||
264 | it('Should have 1 webseed on the first video', async function () { | 326 | it('Should have 1 webseed on the first video', async function () { |
265 | await check1WebSeed(strategy) | 327 | await check1WebSeed() |
328 | await check0PlaylistRedundancies() | ||
266 | await checkStatsWith1Webseed(strategy) | 329 | await checkStatsWith1Webseed(strategy) |
267 | }) | 330 | }) |
268 | 331 | ||
@@ -270,26 +333,28 @@ describe('Test videos redundancy', function () { | |||
270 | return enableRedundancyOnServer1() | 333 | return enableRedundancyOnServer1() |
271 | }) | 334 | }) |
272 | 335 | ||
273 | it('Should have 2 webseed on the first video', async function () { | 336 | it('Should have 2 webseeds on the first video', async function () { |
274 | this.timeout(40000) | 337 | this.timeout(80000) |
275 | 338 | ||
276 | await waitJobs(servers) | 339 | await waitJobs(servers) |
277 | await waitUntilLog(servers[0], 'Duplicated ', 4) | 340 | await waitUntilLog(servers[0], 'Duplicated ', 5) |
278 | await waitJobs(servers) | 341 | await waitJobs(servers) |
279 | 342 | ||
280 | await check2Webseeds(strategy) | 343 | await check2Webseeds() |
344 | await check1PlaylistRedundancies() | ||
281 | await checkStatsWith2Webseed(strategy) | 345 | await checkStatsWith2Webseed(strategy) |
282 | }) | 346 | }) |
283 | 347 | ||
284 | it('Should unfollow on server 1 and remove duplicated videos', async function () { | 348 | it('Should unfollow on server 1 and remove duplicated videos', async function () { |
285 | this.timeout(40000) | 349 | this.timeout(80000) |
286 | 350 | ||
287 | await unfollow(servers[0].url, servers[0].accessToken, servers[1]) | 351 | await unfollow(servers[0].url, servers[0].accessToken, servers[1]) |
288 | 352 | ||
289 | await waitJobs(servers) | 353 | await waitJobs(servers) |
290 | await wait(5000) | 354 | await wait(5000) |
291 | 355 | ||
292 | await check1WebSeed(strategy) | 356 | await check1WebSeed() |
357 | await check0PlaylistRedundancies() | ||
293 | 358 | ||
294 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) | 359 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ 'videos' ]) |
295 | }) | 360 | }) |
@@ -309,7 +374,8 @@ describe('Test videos redundancy', function () { | |||
309 | }) | 374 | }) |
310 | 375 | ||
311 | it('Should have 1 webseed on the first video', async function () { | 376 | it('Should have 1 webseed on the first video', async function () { |
312 | await check1WebSeed(strategy) | 377 | await check1WebSeed() |
378 | await check0PlaylistRedundancies() | ||
313 | await checkStatsWith1Webseed(strategy) | 379 | await checkStatsWith1Webseed(strategy) |
314 | }) | 380 | }) |
315 | 381 | ||
@@ -318,18 +384,19 @@ describe('Test videos redundancy', function () { | |||
318 | }) | 384 | }) |
319 | 385 | ||
320 | it('Should still have 1 webseed on the first video', async function () { | 386 | it('Should still have 1 webseed on the first video', async function () { |
321 | this.timeout(40000) | 387 | this.timeout(80000) |
322 | 388 | ||
323 | await waitJobs(servers) | 389 | await waitJobs(servers) |
324 | await wait(15000) | 390 | await wait(15000) |
325 | await waitJobs(servers) | 391 | await waitJobs(servers) |
326 | 392 | ||
327 | await check1WebSeed(strategy) | 393 | await check1WebSeed() |
394 | await check0PlaylistRedundancies() | ||
328 | await checkStatsWith1Webseed(strategy) | 395 | await checkStatsWith1Webseed(strategy) |
329 | }) | 396 | }) |
330 | 397 | ||
331 | it('Should view 2 times the first video to have > min_views config', async function () { | 398 | it('Should view 2 times the first video to have > min_views config', async function () { |
332 | this.timeout(40000) | 399 | this.timeout(80000) |
333 | 400 | ||
334 | await viewVideo(servers[ 0 ].url, video1Server2UUID) | 401 | await viewVideo(servers[ 0 ].url, video1Server2UUID) |
335 | await viewVideo(servers[ 2 ].url, video1Server2UUID) | 402 | await viewVideo(servers[ 2 ].url, video1Server2UUID) |
@@ -338,14 +405,15 @@ describe('Test videos redundancy', function () { | |||
338 | await waitJobs(servers) | 405 | await waitJobs(servers) |
339 | }) | 406 | }) |
340 | 407 | ||
341 | it('Should have 2 webseed on the first video', async function () { | 408 | it('Should have 2 webseeds on the first video', async function () { |
342 | this.timeout(40000) | 409 | this.timeout(80000) |
343 | 410 | ||
344 | await waitJobs(servers) | 411 | await waitJobs(servers) |
345 | await waitUntilLog(servers[0], 'Duplicated ', 4) | 412 | await waitUntilLog(servers[0], 'Duplicated ', 5) |
346 | await waitJobs(servers) | 413 | await waitJobs(servers) |
347 | 414 | ||
348 | await check2Webseeds(strategy) | 415 | await check2Webseeds() |
416 | await check1PlaylistRedundancies() | ||
349 | await checkStatsWith2Webseed(strategy) | 417 | await checkStatsWith2Webseed(strategy) |
350 | }) | 418 | }) |
351 | 419 | ||
@@ -400,7 +468,7 @@ describe('Test videos redundancy', function () { | |||
400 | }) | 468 | }) |
401 | 469 | ||
402 | it('Should still have 2 webseeds after 10 seconds', async function () { | 470 | it('Should still have 2 webseeds after 10 seconds', async function () { |
403 | this.timeout(40000) | 471 | this.timeout(80000) |
404 | 472 | ||
405 | await wait(10000) | 473 | await wait(10000) |
406 | 474 | ||
@@ -415,11 +483,11 @@ describe('Test videos redundancy', function () { | |||
415 | }) | 483 | }) |
416 | 484 | ||
417 | it('Should stop server 1 and expire video redundancy', async function () { | 485 | it('Should stop server 1 and expire video redundancy', async function () { |
418 | this.timeout(40000) | 486 | this.timeout(80000) |
419 | 487 | ||
420 | killallServers([ servers[0] ]) | 488 | killallServers([ servers[0] ]) |
421 | 489 | ||
422 | await wait(10000) | 490 | await wait(15000) |
423 | 491 | ||
424 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') | 492 | await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2Flocalhost%3A9001') |
425 | }) | 493 | }) |
@@ -441,41 +509,60 @@ describe('Test videos redundancy', function () { | |||
441 | await enableRedundancyOnServer1() | 509 | await enableRedundancyOnServer1() |
442 | 510 | ||
443 | await waitJobs(servers) | 511 | await waitJobs(servers) |
444 | await waitUntilLog(servers[0], 'Duplicated ', 4) | 512 | await waitUntilLog(servers[0], 'Duplicated ', 5) |
445 | await waitJobs(servers) | 513 | await waitJobs(servers) |
446 | 514 | ||
447 | await check2Webseeds(strategy) | 515 | await check2Webseeds() |
516 | await check1PlaylistRedundancies() | ||
448 | await checkStatsWith2Webseed(strategy) | 517 | await checkStatsWith2Webseed(strategy) |
449 | 518 | ||
450 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) | 519 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video 2 server 2' }) |
451 | video2Server2UUID = res.body.video.uuid | 520 | video2Server2UUID = res.body.video.uuid |
452 | }) | 521 | }) |
453 | 522 | ||
454 | it('Should cache video 2 webseed on the first video', async function () { | 523 | it('Should cache video 2 webseeds on the first video', async function () { |
455 | this.timeout(50000) | 524 | this.timeout(120000) |
456 | 525 | ||
457 | await waitJobs(servers) | 526 | await waitJobs(servers) |
458 | 527 | ||
459 | await wait(7000) | 528 | let checked = false |
460 | 529 | ||
461 | try { | 530 | while (checked === false) { |
462 | await check1WebSeed(strategy, video1Server2UUID) | 531 | await wait(1000) |
463 | await check2Webseeds(strategy, video2Server2UUID) | ||
464 | } catch { | ||
465 | await wait(3000) | ||
466 | 532 | ||
467 | try { | 533 | try { |
468 | await check1WebSeed(strategy, video1Server2UUID) | 534 | await check1WebSeed(video1Server2UUID) |
469 | await check2Webseeds(strategy, video2Server2UUID) | 535 | await check0PlaylistRedundancies(video1Server2UUID) |
470 | } catch { | 536 | await check2Webseeds(video2Server2UUID) |
471 | await wait(5000) | 537 | await check1PlaylistRedundancies(video2Server2UUID) |
472 | 538 | ||
473 | await check1WebSeed(strategy, video1Server2UUID) | 539 | checked = true |
474 | await check2Webseeds(strategy, video2Server2UUID) | 540 | } catch { |
541 | checked = false | ||
475 | } | 542 | } |
476 | } | 543 | } |
477 | }) | 544 | }) |
478 | 545 | ||
546 | it('Should disable strategy and remove redundancies', async function () { | ||
547 | this.timeout(80000) | ||
548 | |||
549 | await waitJobs(servers) | ||
550 | |||
551 | killallServers([ servers[ 0 ] ]) | ||
552 | await reRunServer(servers[ 0 ], { | ||
553 | redundancy: { | ||
554 | videos: { | ||
555 | check_interval: '1 second', | ||
556 | strategies: [] | ||
557 | } | ||
558 | } | ||
559 | }) | ||
560 | |||
561 | await waitJobs(servers) | ||
562 | |||
563 | await checkVideoFilesWereRemoved(video1Server2UUID, servers[0].serverNumber, [ join('redundancy', 'hls') ]) | ||
564 | }) | ||
565 | |||
479 | after(function () { | 566 | after(function () { |
480 | return cleanServers() | 567 | return cleanServers() |
481 | }) | 568 | }) |
diff --git a/server/tests/api/search/search-activitypub-video-channels.ts b/server/tests/api/search/search-activitypub-video-channels.ts index a287c5bdf..a411e973b 100644 --- a/server/tests/api/search/search-activitypub-video-channels.ts +++ b/server/tests/api/search/search-activitypub-video-channels.ts | |||
@@ -17,10 +17,10 @@ import { | |||
17 | uploadVideo, | 17 | uploadVideo, |
18 | userLogin, | 18 | userLogin, |
19 | wait | 19 | wait |
20 | } from '../../utils' | 20 | } from '../../../../shared/utils' |
21 | import { waitJobs } from '../../utils/server/jobs' | 21 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
22 | import { VideoChannel } from '../../../../shared/models/videos' | 22 | import { VideoChannel } from '../../../../shared/models/videos' |
23 | import { searchVideoChannel } from '../../utils/search/video-channels' | 23 | import { searchVideoChannel } from '../../../../shared/utils/search/video-channels' |
24 | 24 | ||
25 | const expect = chai.expect | 25 | const expect = chai.expect |
26 | 26 | ||
diff --git a/server/tests/api/search/search-activitypub-videos.ts b/server/tests/api/search/search-activitypub-videos.ts index 28f4fac50..f881917e7 100644 --- a/server/tests/api/search/search-activitypub-videos.ts +++ b/server/tests/api/search/search-activitypub-videos.ts | |||
@@ -16,8 +16,8 @@ import { | |||
16 | uploadVideo, | 16 | uploadVideo, |
17 | wait, | 17 | wait, |
18 | searchVideo | 18 | searchVideo |
19 | } from '../../utils' | 19 | } from '../../../../shared/utils' |
20 | import { waitJobs } from '../../utils/server/jobs' | 20 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
21 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' | 21 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' |
22 | 22 | ||
23 | const expect = chai.expect | 23 | const expect = chai.expect |
diff --git a/server/tests/api/search/search-videos.ts b/server/tests/api/search/search-videos.ts index f1392ffea..50da837da 100644 --- a/server/tests/api/search/search-videos.ts +++ b/server/tests/api/search/search-videos.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | uploadVideo, | 13 | uploadVideo, |
14 | wait, | 14 | wait, |
15 | immutableAssign | 15 | immutableAssign |
16 | } from '../../utils' | 16 | } from '../../../../shared/utils' |
17 | 17 | ||
18 | const expect = chai.expect | 18 | const expect = chai.expect |
19 | 19 | ||
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index facd1688d..0dfe6e4fe 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -4,8 +4,11 @@ import 'mocha' | |||
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { About } from '../../../../shared/models/server/about.model' | 5 | import { About } from '../../../../shared/models/server/about.model' |
6 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' | 6 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' |
7 | import { deleteCustomConfig, getAbout, killallServers, reRunServer } from '../../utils' | ||
8 | import { | 7 | import { |
8 | deleteCustomConfig, | ||
9 | getAbout, | ||
10 | killallServers, | ||
11 | reRunServer, | ||
9 | flushTests, | 12 | flushTests, |
10 | getConfig, | 13 | getConfig, |
11 | getCustomConfig, | 14 | getCustomConfig, |
@@ -13,7 +16,8 @@ import { | |||
13 | runServer, | 16 | runServer, |
14 | setAccessTokensToServers, | 17 | setAccessTokensToServers, |
15 | updateCustomConfig | 18 | updateCustomConfig |
16 | } from '../../utils/index' | 19 | } from '../../../../shared/utils' |
20 | import { ServerConfig } from '../../../../shared/models' | ||
17 | 21 | ||
18 | const expect = chai.expect | 22 | const expect = chai.expect |
19 | 23 | ||
@@ -29,23 +33,32 @@ function checkInitialConfig (data: CustomConfig) { | |||
29 | expect(data.instance.defaultNSFWPolicy).to.equal('display') | 33 | expect(data.instance.defaultNSFWPolicy).to.equal('display') |
30 | expect(data.instance.customizations.css).to.be.empty | 34 | expect(data.instance.customizations.css).to.be.empty |
31 | expect(data.instance.customizations.javascript).to.be.empty | 35 | expect(data.instance.customizations.javascript).to.be.empty |
36 | |||
32 | expect(data.services.twitter.username).to.equal('@Chocobozzz') | 37 | expect(data.services.twitter.username).to.equal('@Chocobozzz') |
33 | expect(data.services.twitter.whitelisted).to.be.false | 38 | expect(data.services.twitter.whitelisted).to.be.false |
39 | |||
34 | expect(data.cache.previews.size).to.equal(1) | 40 | expect(data.cache.previews.size).to.equal(1) |
35 | expect(data.cache.captions.size).to.equal(1) | 41 | expect(data.cache.captions.size).to.equal(1) |
42 | |||
36 | expect(data.signup.enabled).to.be.true | 43 | expect(data.signup.enabled).to.be.true |
37 | expect(data.signup.limit).to.equal(4) | 44 | expect(data.signup.limit).to.equal(4) |
38 | expect(data.signup.requiresEmailVerification).to.be.false | 45 | expect(data.signup.requiresEmailVerification).to.be.false |
46 | |||
39 | expect(data.admin.email).to.equal('admin1@example.com') | 47 | expect(data.admin.email).to.equal('admin1@example.com') |
48 | expect(data.contactForm.enabled).to.be.true | ||
49 | |||
40 | expect(data.user.videoQuota).to.equal(5242880) | 50 | expect(data.user.videoQuota).to.equal(5242880) |
41 | expect(data.user.videoQuotaDaily).to.equal(-1) | 51 | expect(data.user.videoQuotaDaily).to.equal(-1) |
42 | expect(data.transcoding.enabled).to.be.false | 52 | expect(data.transcoding.enabled).to.be.false |
53 | expect(data.transcoding.allowAdditionalExtensions).to.be.false | ||
43 | expect(data.transcoding.threads).to.equal(2) | 54 | expect(data.transcoding.threads).to.equal(2) |
44 | expect(data.transcoding.resolutions['240p']).to.be.true | 55 | expect(data.transcoding.resolutions['240p']).to.be.true |
45 | expect(data.transcoding.resolutions['360p']).to.be.true | 56 | expect(data.transcoding.resolutions['360p']).to.be.true |
46 | expect(data.transcoding.resolutions['480p']).to.be.true | 57 | expect(data.transcoding.resolutions['480p']).to.be.true |
47 | expect(data.transcoding.resolutions['720p']).to.be.true | 58 | expect(data.transcoding.resolutions['720p']).to.be.true |
48 | expect(data.transcoding.resolutions['1080p']).to.be.true | 59 | expect(data.transcoding.resolutions['1080p']).to.be.true |
60 | expect(data.transcoding.hls.enabled).to.be.true | ||
61 | |||
49 | expect(data.import.videos.http.enabled).to.be.true | 62 | expect(data.import.videos.http.enabled).to.be.true |
50 | expect(data.import.videos.torrent.enabled).to.be.true | 63 | expect(data.import.videos.torrent.enabled).to.be.true |
51 | } | 64 | } |
@@ -59,23 +72,33 @@ function checkUpdatedConfig (data: CustomConfig) { | |||
59 | expect(data.instance.defaultNSFWPolicy).to.equal('blur') | 72 | expect(data.instance.defaultNSFWPolicy).to.equal('blur') |
60 | expect(data.instance.customizations.javascript).to.equal('alert("coucou")') | 73 | expect(data.instance.customizations.javascript).to.equal('alert("coucou")') |
61 | expect(data.instance.customizations.css).to.equal('body { background-color: red; }') | 74 | expect(data.instance.customizations.css).to.equal('body { background-color: red; }') |
75 | |||
62 | expect(data.services.twitter.username).to.equal('@Kuja') | 76 | expect(data.services.twitter.username).to.equal('@Kuja') |
63 | expect(data.services.twitter.whitelisted).to.be.true | 77 | expect(data.services.twitter.whitelisted).to.be.true |
78 | |||
64 | expect(data.cache.previews.size).to.equal(2) | 79 | expect(data.cache.previews.size).to.equal(2) |
65 | expect(data.cache.captions.size).to.equal(3) | 80 | expect(data.cache.captions.size).to.equal(3) |
81 | |||
66 | expect(data.signup.enabled).to.be.false | 82 | expect(data.signup.enabled).to.be.false |
67 | expect(data.signup.limit).to.equal(5) | 83 | expect(data.signup.limit).to.equal(5) |
68 | expect(data.signup.requiresEmailVerification).to.be.true | 84 | expect(data.signup.requiresEmailVerification).to.be.true |
85 | |||
69 | expect(data.admin.email).to.equal('superadmin1@example.com') | 86 | expect(data.admin.email).to.equal('superadmin1@example.com') |
87 | expect(data.contactForm.enabled).to.be.false | ||
88 | |||
70 | expect(data.user.videoQuota).to.equal(5242881) | 89 | expect(data.user.videoQuota).to.equal(5242881) |
71 | expect(data.user.videoQuotaDaily).to.equal(318742) | 90 | expect(data.user.videoQuotaDaily).to.equal(318742) |
91 | |||
72 | expect(data.transcoding.enabled).to.be.true | 92 | expect(data.transcoding.enabled).to.be.true |
73 | expect(data.transcoding.threads).to.equal(1) | 93 | expect(data.transcoding.threads).to.equal(1) |
94 | expect(data.transcoding.allowAdditionalExtensions).to.be.true | ||
74 | expect(data.transcoding.resolutions['240p']).to.be.false | 95 | expect(data.transcoding.resolutions['240p']).to.be.false |
75 | expect(data.transcoding.resolutions['360p']).to.be.true | 96 | expect(data.transcoding.resolutions['360p']).to.be.true |
76 | expect(data.transcoding.resolutions['480p']).to.be.true | 97 | expect(data.transcoding.resolutions['480p']).to.be.true |
77 | expect(data.transcoding.resolutions['720p']).to.be.false | 98 | expect(data.transcoding.resolutions['720p']).to.be.false |
78 | expect(data.transcoding.resolutions['1080p']).to.be.false | 99 | expect(data.transcoding.resolutions['1080p']).to.be.false |
100 | expect(data.transcoding.hls.enabled).to.be.false | ||
101 | |||
79 | expect(data.import.videos.http.enabled).to.be.false | 102 | expect(data.import.videos.http.enabled).to.be.false |
80 | expect(data.import.videos.torrent.enabled).to.be.false | 103 | expect(data.import.videos.torrent.enabled).to.be.false |
81 | } | 104 | } |
@@ -93,7 +116,7 @@ describe('Test config', function () { | |||
93 | 116 | ||
94 | it('Should have a correct config on a server with registration enabled', async function () { | 117 | it('Should have a correct config on a server with registration enabled', async function () { |
95 | const res = await getConfig(server.url) | 118 | const res = await getConfig(server.url) |
96 | const data = res.body | 119 | const data: ServerConfig = res.body |
97 | 120 | ||
98 | expect(data.signup.allowed).to.be.true | 121 | expect(data.signup.allowed).to.be.true |
99 | }) | 122 | }) |
@@ -108,11 +131,23 @@ describe('Test config', function () { | |||
108 | ]) | 131 | ]) |
109 | 132 | ||
110 | const res = await getConfig(server.url) | 133 | const res = await getConfig(server.url) |
111 | const data = res.body | 134 | const data: ServerConfig = res.body |
112 | 135 | ||
113 | expect(data.signup.allowed).to.be.false | 136 | expect(data.signup.allowed).to.be.false |
114 | }) | 137 | }) |
115 | 138 | ||
139 | it('Should have the correct video allowed extensions', async function () { | ||
140 | const res = await getConfig(server.url) | ||
141 | const data: ServerConfig = res.body | ||
142 | |||
143 | expect(data.video.file.extensions).to.have.lengthOf(3) | ||
144 | expect(data.video.file.extensions).to.contain('.mp4') | ||
145 | expect(data.video.file.extensions).to.contain('.webm') | ||
146 | expect(data.video.file.extensions).to.contain('.ogv') | ||
147 | |||
148 | expect(data.contactForm.enabled).to.be.true | ||
149 | }) | ||
150 | |||
116 | it('Should get the customized configuration', async function () { | 151 | it('Should get the customized configuration', async function () { |
117 | const res = await getCustomConfig(server.url, server.accessToken) | 152 | const res = await getCustomConfig(server.url, server.accessToken) |
118 | const data = res.body as CustomConfig | 153 | const data = res.body as CustomConfig |
@@ -156,12 +191,16 @@ describe('Test config', function () { | |||
156 | admin: { | 191 | admin: { |
157 | email: 'superadmin1@example.com' | 192 | email: 'superadmin1@example.com' |
158 | }, | 193 | }, |
194 | contactForm: { | ||
195 | enabled: false | ||
196 | }, | ||
159 | user: { | 197 | user: { |
160 | videoQuota: 5242881, | 198 | videoQuota: 5242881, |
161 | videoQuotaDaily: 318742 | 199 | videoQuotaDaily: 318742 |
162 | }, | 200 | }, |
163 | transcoding: { | 201 | transcoding: { |
164 | enabled: true, | 202 | enabled: true, |
203 | allowAdditionalExtensions: true, | ||
165 | threads: 1, | 204 | threads: 1, |
166 | resolutions: { | 205 | resolutions: { |
167 | '240p': false, | 206 | '240p': false, |
@@ -169,6 +208,9 @@ describe('Test config', function () { | |||
169 | '480p': true, | 208 | '480p': true, |
170 | '720p': false, | 209 | '720p': false, |
171 | '1080p': false | 210 | '1080p': false |
211 | }, | ||
212 | hls: { | ||
213 | enabled: false | ||
172 | } | 214 | } |
173 | }, | 215 | }, |
174 | import: { | 216 | import: { |
@@ -190,6 +232,18 @@ describe('Test config', function () { | |||
190 | checkUpdatedConfig(data) | 232 | checkUpdatedConfig(data) |
191 | }) | 233 | }) |
192 | 234 | ||
235 | it('Should have the correct updated video allowed extensions', async function () { | ||
236 | const res = await getConfig(server.url) | ||
237 | const data: ServerConfig = res.body | ||
238 | |||
239 | expect(data.video.file.extensions).to.have.length.above(3) | ||
240 | expect(data.video.file.extensions).to.contain('.mp4') | ||
241 | expect(data.video.file.extensions).to.contain('.webm') | ||
242 | expect(data.video.file.extensions).to.contain('.ogv') | ||
243 | expect(data.video.file.extensions).to.contain('.flv') | ||
244 | expect(data.video.file.extensions).to.contain('.mkv') | ||
245 | }) | ||
246 | |||
193 | it('Should have the configuration updated after a restart', async function () { | 247 | it('Should have the configuration updated after a restart', async function () { |
194 | this.timeout(10000) | 248 | this.timeout(10000) |
195 | 249 | ||
diff --git a/server/tests/api/server/contact-form.ts b/server/tests/api/server/contact-form.ts new file mode 100644 index 000000000..93221d0a3 --- /dev/null +++ b/server/tests/api/server/contact-form.ts | |||
@@ -0,0 +1,86 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { flushTests, killallServers, runServer, ServerInfo, setAccessTokensToServers, wait } from '../../../../shared/utils' | ||
6 | import { MockSmtpServer } from '../../../../shared/utils/miscs/email' | ||
7 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
8 | import { sendContactForm } from '../../../../shared/utils/server/contact-form' | ||
9 | |||
10 | const expect = chai.expect | ||
11 | |||
12 | describe('Test contact form', function () { | ||
13 | let server: ServerInfo | ||
14 | const emails: object[] = [] | ||
15 | |||
16 | before(async function () { | ||
17 | this.timeout(30000) | ||
18 | |||
19 | await MockSmtpServer.Instance.collectEmails(emails) | ||
20 | |||
21 | await flushTests() | ||
22 | |||
23 | const overrideConfig = { | ||
24 | smtp: { | ||
25 | hostname: 'localhost' | ||
26 | } | ||
27 | } | ||
28 | server = await runServer(1, overrideConfig) | ||
29 | await setAccessTokensToServers([ server ]) | ||
30 | }) | ||
31 | |||
32 | it('Should send a contact form', async function () { | ||
33 | this.timeout(10000) | ||
34 | |||
35 | await sendContactForm({ | ||
36 | url: server.url, | ||
37 | fromEmail: 'toto@example.com', | ||
38 | body: 'my super message', | ||
39 | fromName: 'Super toto' | ||
40 | }) | ||
41 | |||
42 | await waitJobs(server) | ||
43 | |||
44 | expect(emails).to.have.lengthOf(1) | ||
45 | |||
46 | const email = emails[0] | ||
47 | |||
48 | expect(email['from'][0]['address']).equal('toto@example.com') | ||
49 | expect(email['to'][0]['address']).equal('admin1@example.com') | ||
50 | expect(email['subject']).contains('Contact form') | ||
51 | expect(email['text']).contains('my super message') | ||
52 | }) | ||
53 | |||
54 | it('Should not be able to send another contact form because of the anti spam checker', async function () { | ||
55 | await sendContactForm({ | ||
56 | url: server.url, | ||
57 | fromEmail: 'toto@example.com', | ||
58 | body: 'my super message', | ||
59 | fromName: 'Super toto' | ||
60 | }) | ||
61 | |||
62 | await sendContactForm({ | ||
63 | url: server.url, | ||
64 | fromEmail: 'toto@example.com', | ||
65 | body: 'my super message', | ||
66 | fromName: 'Super toto', | ||
67 | expectedStatus: 403 | ||
68 | }) | ||
69 | }) | ||
70 | |||
71 | it('Should be able to send another contact form after a while', async function () { | ||
72 | await wait(1000) | ||
73 | |||
74 | await sendContactForm({ | ||
75 | url: server.url, | ||
76 | fromEmail: 'toto@example.com', | ||
77 | body: 'my super message', | ||
78 | fromName: 'Super toto' | ||
79 | }) | ||
80 | }) | ||
81 | |||
82 | after(async function () { | ||
83 | MockSmtpServer.Instance.kill() | ||
84 | killallServers([ server ]) | ||
85 | }) | ||
86 | }) | ||
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts index 713a27143..f96c57b66 100644 --- a/server/tests/api/server/email.ts +++ b/server/tests/api/server/email.ts | |||
@@ -14,11 +14,14 @@ import { | |||
14 | unblockUser, | 14 | unblockUser, |
15 | uploadVideo, | 15 | uploadVideo, |
16 | userLogin, | 16 | userLogin, |
17 | verifyEmail | 17 | verifyEmail, |
18 | } from '../../utils' | 18 | flushTests, |
19 | import { flushTests, killallServers, ServerInfo, setAccessTokensToServers } from '../../utils/index' | 19 | killallServers, |
20 | import { mockSmtpServer } from '../../utils/miscs/email' | 20 | ServerInfo, |
21 | import { waitJobs } from '../../utils/server/jobs' | 21 | setAccessTokensToServers |
22 | } from '../../../../shared/utils' | ||
23 | import { MockSmtpServer } from '../../../../shared/utils/miscs/email' | ||
24 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
22 | 25 | ||
23 | const expect = chai.expect | 26 | const expect = chai.expect |
24 | 27 | ||
@@ -38,7 +41,7 @@ describe('Test emails', function () { | |||
38 | before(async function () { | 41 | before(async function () { |
39 | this.timeout(30000) | 42 | this.timeout(30000) |
40 | 43 | ||
41 | await mockSmtpServer(emails) | 44 | await MockSmtpServer.Instance.collectEmails(emails) |
42 | 45 | ||
43 | await flushTests() | 46 | await flushTests() |
44 | 47 | ||
@@ -248,6 +251,7 @@ describe('Test emails', function () { | |||
248 | }) | 251 | }) |
249 | 252 | ||
250 | after(async function () { | 253 | after(async function () { |
254 | MockSmtpServer.Instance.kill() | ||
251 | killallServers([ server ]) | 255 | killallServers([ server ]) |
252 | }) | 256 | }) |
253 | }) | 257 | }) |
diff --git a/server/tests/api/server/follow-constraints.ts b/server/tests/api/server/follow-constraints.ts new file mode 100644 index 000000000..8bb073c41 --- /dev/null +++ b/server/tests/api/server/follow-constraints.ts | |||
@@ -0,0 +1,225 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | doubleFollow, | ||
7 | getAccountVideos, | ||
8 | getVideo, | ||
9 | getVideoChannelVideos, | ||
10 | getVideoWithToken, | ||
11 | flushAndRunMultipleServers, | ||
12 | killallServers, | ||
13 | ServerInfo, | ||
14 | setAccessTokensToServers, | ||
15 | uploadVideo | ||
16 | } from '../../../../shared/utils' | ||
17 | import { unfollow } from '../../../../shared/utils/server/follows' | ||
18 | import { userLogin } from '../../../../shared/utils/users/login' | ||
19 | import { createUser } from '../../../../shared/utils/users/users' | ||
20 | |||
21 | const expect = chai.expect | ||
22 | |||
23 | describe('Test follow constraints', function () { | ||
24 | let servers: ServerInfo[] = [] | ||
25 | let video1UUID: string | ||
26 | let video2UUID: string | ||
27 | let userAccessToken: string | ||
28 | |||
29 | before(async function () { | ||
30 | this.timeout(30000) | ||
31 | |||
32 | servers = await flushAndRunMultipleServers(2) | ||
33 | |||
34 | // Get the access tokens | ||
35 | await setAccessTokensToServers(servers) | ||
36 | |||
37 | { | ||
38 | const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'video server 1' }) | ||
39 | video1UUID = res.body.video.uuid | ||
40 | } | ||
41 | { | ||
42 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, { name: 'video server 2' }) | ||
43 | video2UUID = res.body.video.uuid | ||
44 | } | ||
45 | |||
46 | const user = { | ||
47 | username: 'user1', | ||
48 | password: 'super_password' | ||
49 | } | ||
50 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | ||
51 | userAccessToken = await userLogin(servers[0], user) | ||
52 | |||
53 | await doubleFollow(servers[0], servers[1]) | ||
54 | }) | ||
55 | |||
56 | describe('With a followed instance', function () { | ||
57 | |||
58 | describe('With an unlogged user', function () { | ||
59 | |||
60 | it('Should get the local video', async function () { | ||
61 | await getVideo(servers[0].url, video1UUID, 200) | ||
62 | }) | ||
63 | |||
64 | it('Should get the remote video', async function () { | ||
65 | await getVideo(servers[0].url, video2UUID, 200) | ||
66 | }) | ||
67 | |||
68 | it('Should list local account videos', async function () { | ||
69 | const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:9001', 0, 5) | ||
70 | |||
71 | expect(res.body.total).to.equal(1) | ||
72 | expect(res.body.data).to.have.lengthOf(1) | ||
73 | }) | ||
74 | |||
75 | it('Should list remote account videos', async function () { | ||
76 | const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:9002', 0, 5) | ||
77 | |||
78 | expect(res.body.total).to.equal(1) | ||
79 | expect(res.body.data).to.have.lengthOf(1) | ||
80 | }) | ||
81 | |||
82 | it('Should list local channel videos', async function () { | ||
83 | const res = await getVideoChannelVideos(servers[0].url, undefined, 'root_channel@localhost:9001', 0, 5) | ||
84 | |||
85 | expect(res.body.total).to.equal(1) | ||
86 | expect(res.body.data).to.have.lengthOf(1) | ||
87 | }) | ||
88 | |||
89 | it('Should list remote channel videos', async function () { | ||
90 | const res = await getVideoChannelVideos(servers[0].url, undefined, 'root_channel@localhost:9002', 0, 5) | ||
91 | |||
92 | expect(res.body.total).to.equal(1) | ||
93 | expect(res.body.data).to.have.lengthOf(1) | ||
94 | }) | ||
95 | }) | ||
96 | |||
97 | describe('With a logged user', function () { | ||
98 | it('Should get the local video', async function () { | ||
99 | await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200) | ||
100 | }) | ||
101 | |||
102 | it('Should get the remote video', async function () { | ||
103 | await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200) | ||
104 | }) | ||
105 | |||
106 | it('Should list local account videos', async function () { | ||
107 | const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:9001', 0, 5) | ||
108 | |||
109 | expect(res.body.total).to.equal(1) | ||
110 | expect(res.body.data).to.have.lengthOf(1) | ||
111 | }) | ||
112 | |||
113 | it('Should list remote account videos', async function () { | ||
114 | const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:9002', 0, 5) | ||
115 | |||
116 | expect(res.body.total).to.equal(1) | ||
117 | expect(res.body.data).to.have.lengthOf(1) | ||
118 | }) | ||
119 | |||
120 | it('Should list local channel videos', async function () { | ||
121 | const res = await getVideoChannelVideos(servers[0].url, userAccessToken, 'root_channel@localhost:9001', 0, 5) | ||
122 | |||
123 | expect(res.body.total).to.equal(1) | ||
124 | expect(res.body.data).to.have.lengthOf(1) | ||
125 | }) | ||
126 | |||
127 | it('Should list remote channel videos', async function () { | ||
128 | const res = await getVideoChannelVideos(servers[0].url, userAccessToken, 'root_channel@localhost:9002', 0, 5) | ||
129 | |||
130 | expect(res.body.total).to.equal(1) | ||
131 | expect(res.body.data).to.have.lengthOf(1) | ||
132 | }) | ||
133 | }) | ||
134 | }) | ||
135 | |||
136 | describe('With a non followed instance', function () { | ||
137 | |||
138 | before(async function () { | ||
139 | this.timeout(30000) | ||
140 | |||
141 | await unfollow(servers[0].url, servers[0].accessToken, servers[1]) | ||
142 | }) | ||
143 | |||
144 | describe('With an unlogged user', function () { | ||
145 | |||
146 | it('Should get the local video', async function () { | ||
147 | await getVideo(servers[0].url, video1UUID, 200) | ||
148 | }) | ||
149 | |||
150 | it('Should not get the remote video', async function () { | ||
151 | await getVideo(servers[0].url, video2UUID, 403) | ||
152 | }) | ||
153 | |||
154 | it('Should list local account videos', async function () { | ||
155 | const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:9001', 0, 5) | ||
156 | |||
157 | expect(res.body.total).to.equal(1) | ||
158 | expect(res.body.data).to.have.lengthOf(1) | ||
159 | }) | ||
160 | |||
161 | it('Should not list remote account videos', async function () { | ||
162 | const res = await getAccountVideos(servers[0].url, undefined, 'root@localhost:9002', 0, 5) | ||
163 | |||
164 | expect(res.body.total).to.equal(0) | ||
165 | expect(res.body.data).to.have.lengthOf(0) | ||
166 | }) | ||
167 | |||
168 | it('Should list local channel videos', async function () { | ||
169 | const res = await getVideoChannelVideos(servers[0].url, undefined, 'root_channel@localhost:9001', 0, 5) | ||
170 | |||
171 | expect(res.body.total).to.equal(1) | ||
172 | expect(res.body.data).to.have.lengthOf(1) | ||
173 | }) | ||
174 | |||
175 | it('Should not list remote channel videos', async function () { | ||
176 | const res = await getVideoChannelVideos(servers[0].url, undefined, 'root_channel@localhost:9002', 0, 5) | ||
177 | |||
178 | expect(res.body.total).to.equal(0) | ||
179 | expect(res.body.data).to.have.lengthOf(0) | ||
180 | }) | ||
181 | }) | ||
182 | |||
183 | describe('With a logged user', function () { | ||
184 | it('Should get the local video', async function () { | ||
185 | await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200) | ||
186 | }) | ||
187 | |||
188 | it('Should get the remote video', async function () { | ||
189 | await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200) | ||
190 | }) | ||
191 | |||
192 | it('Should list local account videos', async function () { | ||
193 | const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:9001', 0, 5) | ||
194 | |||
195 | expect(res.body.total).to.equal(1) | ||
196 | expect(res.body.data).to.have.lengthOf(1) | ||
197 | }) | ||
198 | |||
199 | it('Should list remote account videos', async function () { | ||
200 | const res = await getAccountVideos(servers[0].url, userAccessToken, 'root@localhost:9002', 0, 5) | ||
201 | |||
202 | expect(res.body.total).to.equal(1) | ||
203 | expect(res.body.data).to.have.lengthOf(1) | ||
204 | }) | ||
205 | |||
206 | it('Should list local channel videos', async function () { | ||
207 | const res = await getVideoChannelVideos(servers[0].url, userAccessToken, 'root_channel@localhost:9001', 0, 5) | ||
208 | |||
209 | expect(res.body.total).to.equal(1) | ||
210 | expect(res.body.data).to.have.lengthOf(1) | ||
211 | }) | ||
212 | |||
213 | it('Should list remote channel videos', async function () { | ||
214 | const res = await getVideoChannelVideos(servers[0].url, userAccessToken, 'root_channel@localhost:9002', 0, 5) | ||
215 | |||
216 | expect(res.body.total).to.equal(1) | ||
217 | expect(res.body.data).to.have.lengthOf(1) | ||
218 | }) | ||
219 | }) | ||
220 | }) | ||
221 | |||
222 | after(async function () { | ||
223 | killallServers(servers) | ||
224 | }) | ||
225 | }) | ||
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index e8914a9d4..ad4c87c73 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -4,7 +4,7 @@ import * as chai from 'chai' | |||
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' | 5 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' |
6 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | 6 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' |
7 | import { completeVideoCheck } from '../../utils' | 7 | import { completeVideoCheck } from '../../../../shared/utils' |
8 | import { | 8 | import { |
9 | flushAndRunMultipleServers, | 9 | flushAndRunMultipleServers, |
10 | getVideosList, | 10 | getVideosList, |
@@ -12,21 +12,26 @@ import { | |||
12 | ServerInfo, | 12 | ServerInfo, |
13 | setAccessTokensToServers, | 13 | setAccessTokensToServers, |
14 | uploadVideo | 14 | uploadVideo |
15 | } from '../../utils/index' | 15 | } from '../../../../shared/utils/index' |
16 | import { dateIsValid } from '../../utils/miscs/miscs' | 16 | import { dateIsValid } from '../../../../shared/utils/miscs/miscs' |
17 | import { follow, getFollowersListPaginationAndSort, getFollowingListPaginationAndSort, unfollow } from '../../utils/server/follows' | 17 | import { |
18 | import { expectAccountFollows } from '../../utils/users/accounts' | 18 | follow, |
19 | import { userLogin } from '../../utils/users/login' | 19 | getFollowersListPaginationAndSort, |
20 | import { createUser } from '../../utils/users/users' | 20 | getFollowingListPaginationAndSort, |
21 | unfollow | ||
22 | } from '../../../../shared/utils/server/follows' | ||
23 | import { expectAccountFollows } from '../../../../shared/utils/users/accounts' | ||
24 | import { userLogin } from '../../../../shared/utils/users/login' | ||
25 | import { createUser } from '../../../../shared/utils/users/users' | ||
21 | import { | 26 | import { |
22 | addVideoCommentReply, | 27 | addVideoCommentReply, |
23 | addVideoCommentThread, | 28 | addVideoCommentThread, |
24 | getVideoCommentThreads, | 29 | getVideoCommentThreads, |
25 | getVideoThreadComments | 30 | getVideoThreadComments |
26 | } from '../../utils/videos/video-comments' | 31 | } from '../../../../shared/utils/videos/video-comments' |
27 | import { rateVideo } from '../../utils/videos/videos' | 32 | import { rateVideo } from '../../../../shared/utils/videos/videos' |
28 | import { waitJobs } from '../../utils/server/jobs' | 33 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
29 | import { createVideoCaption, listVideoCaptions, testCaptionFile } from '../../utils/videos/video-captions' | 34 | import { createVideoCaption, listVideoCaptions, testCaptionFile } from '../../../../shared/utils/videos/video-captions' |
30 | import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' | 35 | import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' |
31 | 36 | ||
32 | const expect = chai.expect | 37 | const expect = chai.expect |
@@ -93,7 +98,26 @@ describe('Test follows', function () { | |||
93 | expect(server3Follow.state).to.equal('accepted') | 98 | expect(server3Follow.state).to.equal('accepted') |
94 | }) | 99 | }) |
95 | 100 | ||
96 | it('Should have 0 followings on server 1 and 2', async function () { | 101 | it('Should search followings on server 1', async function () { |
102 | { | ||
103 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt', ':9002') | ||
104 | const follows = res.body.data | ||
105 | |||
106 | expect(res.body.total).to.equal(1) | ||
107 | expect(follows.length).to.equal(1) | ||
108 | expect(follows[ 0 ].following.host).to.equal('localhost:9002') | ||
109 | } | ||
110 | |||
111 | { | ||
112 | const res = await getFollowingListPaginationAndSort(servers[ 0 ].url, 0, 1, 'createdAt', 'bla') | ||
113 | const follows = res.body.data | ||
114 | |||
115 | expect(res.body.total).to.equal(0) | ||
116 | expect(follows.length).to.equal(0) | ||
117 | } | ||
118 | }) | ||
119 | |||
120 | it('Should have 0 followings on server 2 and 3', async function () { | ||
97 | for (const server of [ servers[1], servers[2] ]) { | 121 | for (const server of [ servers[1], servers[2] ]) { |
98 | const res = await getFollowingListPaginationAndSort(server.url, 0, 5, 'createdAt') | 122 | const res = await getFollowingListPaginationAndSort(server.url, 0, 5, 'createdAt') |
99 | const follows = res.body.data | 123 | const follows = res.body.data |
@@ -116,6 +140,25 @@ describe('Test follows', function () { | |||
116 | } | 140 | } |
117 | }) | 141 | }) |
118 | 142 | ||
143 | it('Should search followers on server 2', async function () { | ||
144 | { | ||
145 | const res = await getFollowersListPaginationAndSort(servers[ 2 ].url, 0, 5, 'createdAt', '9001') | ||
146 | const follows = res.body.data | ||
147 | |||
148 | expect(res.body.total).to.equal(1) | ||
149 | expect(follows.length).to.equal(1) | ||
150 | expect(follows[ 0 ].following.host).to.equal('localhost:9003') | ||
151 | } | ||
152 | |||
153 | { | ||
154 | const res = await getFollowersListPaginationAndSort(servers[ 2 ].url, 0, 5, 'createdAt', 'bla') | ||
155 | const follows = res.body.data | ||
156 | |||
157 | expect(res.body.total).to.equal(0) | ||
158 | expect(follows.length).to.equal(0) | ||
159 | } | ||
160 | }) | ||
161 | |||
119 | it('Should have 0 followers on server 1', async function () { | 162 | it('Should have 0 followers on server 1', async function () { |
120 | const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') | 163 | const res = await getFollowersListPaginationAndSort(servers[0].url, 0, 5, 'createdAt') |
121 | const follows = res.body.data | 164 | const follows = res.body.data |
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index b0a3d029a..cd5acbe16 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts | |||
@@ -5,24 +5,30 @@ import 'mocha' | |||
5 | import { JobState, Video } from '../../../../shared/models' | 5 | import { JobState, Video } from '../../../../shared/models' |
6 | import { VideoPrivacy } from '../../../../shared/models/videos' | 6 | import { VideoPrivacy } from '../../../../shared/models/videos' |
7 | import { VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | 7 | import { VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' |
8 | import { completeVideoCheck, getVideo, immutableAssign, reRunServer, unfollow, viewVideo } from '../../utils' | 8 | |
9 | import { | 9 | import { |
10 | completeVideoCheck, | ||
10 | flushAndRunMultipleServers, | 11 | flushAndRunMultipleServers, |
12 | getVideo, | ||
11 | getVideosList, | 13 | getVideosList, |
14 | immutableAssign, | ||
12 | killallServers, | 15 | killallServers, |
16 | reRunServer, | ||
13 | ServerInfo, | 17 | ServerInfo, |
14 | setAccessTokensToServers, | 18 | setAccessTokensToServers, |
19 | unfollow, | ||
20 | updateVideo, | ||
15 | uploadVideo, | 21 | uploadVideo, |
16 | wait | 22 | wait |
17 | } from '../../utils/index' | 23 | } from '../../../../shared/utils' |
18 | import { follow, getFollowersListPaginationAndSort } from '../../utils/server/follows' | 24 | import { follow, getFollowersListPaginationAndSort } from '../../../../shared/utils/server/follows' |
19 | import { getJobsListPaginationAndSort, waitJobs } from '../../utils/server/jobs' | 25 | import { getJobsListPaginationAndSort, waitJobs } from '../../../../shared/utils/server/jobs' |
20 | import { | 26 | import { |
21 | addVideoCommentReply, | 27 | addVideoCommentReply, |
22 | addVideoCommentThread, | 28 | addVideoCommentThread, |
23 | getVideoCommentThreads, | 29 | getVideoCommentThreads, |
24 | getVideoThreadComments | 30 | getVideoThreadComments |
25 | } from '../../utils/videos/video-comments' | 31 | } from '../../../../shared/utils/videos/video-comments' |
26 | 32 | ||
27 | const expect = chai.expect | 33 | const expect = chai.expect |
28 | 34 | ||
@@ -195,15 +201,15 @@ describe('Test handle downs', function () { | |||
195 | expect(res.body.data).to.have.lengthOf(2) | 201 | expect(res.body.data).to.have.lengthOf(2) |
196 | }) | 202 | }) |
197 | 203 | ||
198 | it('Should send a view to server 3, and automatically fetch the video', async function () { | 204 | it('Should send an update to server 3, and automatically fetch the video', async function () { |
199 | this.timeout(15000) | 205 | this.timeout(15000) |
200 | 206 | ||
201 | const res1 = await getVideosList(servers[2].url) | 207 | const res1 = await getVideosList(servers[2].url) |
202 | expect(res1.body.data).to.be.an('array') | 208 | expect(res1.body.data).to.be.an('array') |
203 | expect(res1.body.data).to.have.lengthOf(11) | 209 | expect(res1.body.data).to.have.lengthOf(11) |
204 | 210 | ||
205 | await viewVideo(servers[0].url, missedVideo1.uuid) | 211 | await updateVideo(servers[0].url, servers[0].accessToken, missedVideo1.uuid, { }) |
206 | await viewVideo(servers[0].url, unlistedVideo.uuid) | 212 | await updateVideo(servers[0].url, servers[0].accessToken, unlistedVideo.uuid, { }) |
207 | 213 | ||
208 | await waitJobs(servers) | 214 | await waitJobs(servers) |
209 | 215 | ||
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts index c74c68a33..1f80cc6cf 100644 --- a/server/tests/api/server/index.ts +++ b/server/tests/api/server/index.ts | |||
@@ -1,9 +1,11 @@ | |||
1 | import './config' | 1 | import './config' |
2 | import './contact-form' | ||
2 | import './email' | 3 | import './email' |
4 | import './follow-constraints' | ||
3 | import './follows' | 5 | import './follows' |
4 | import './handle-down' | 6 | import './handle-down' |
5 | import './jobs' | 7 | import './jobs' |
6 | import './redundancy' | ||
7 | import './reverse-proxy' | 8 | import './reverse-proxy' |
8 | import './stats' | 9 | import './stats' |
9 | import './tracker' | 10 | import './tracker' |
11 | import './no-client' | ||
diff --git a/server/tests/api/server/jobs.ts b/server/tests/api/server/jobs.ts index cd59d9a1b..52948b1d6 100644 --- a/server/tests/api/server/jobs.ts +++ b/server/tests/api/server/jobs.ts | |||
@@ -2,12 +2,12 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { killallServers, ServerInfo, setAccessTokensToServers } from '../../utils/index' | 5 | import { killallServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/utils/index' |
6 | import { doubleFollow } from '../../utils/server/follows' | 6 | import { doubleFollow } from '../../../../shared/utils/server/follows' |
7 | import { getJobsList, getJobsListPaginationAndSort, waitJobs } from '../../utils/server/jobs' | 7 | import { getJobsList, getJobsListPaginationAndSort, waitJobs } from '../../../../shared/utils/server/jobs' |
8 | import { flushAndRunMultipleServers } from '../../utils/server/servers' | 8 | import { flushAndRunMultipleServers } from '../../../../shared/utils/server/servers' |
9 | import { uploadVideo } from '../../utils/videos/videos' | 9 | import { uploadVideo } from '../../../../shared/utils/videos/videos' |
10 | import { dateIsValid } from '../../utils/miscs/miscs' | 10 | import { dateIsValid } from '../../../../shared/utils/miscs/miscs' |
11 | 11 | ||
12 | const expect = chai.expect | 12 | const expect = chai.expect |
13 | 13 | ||
diff --git a/server/tests/api/server/no-client.ts b/server/tests/api/server/no-client.ts new file mode 100644 index 000000000..3b95ce945 --- /dev/null +++ b/server/tests/api/server/no-client.ts | |||
@@ -0,0 +1,36 @@ | |||
1 | import 'mocha' | ||
2 | import * as request from 'supertest' | ||
3 | import { | ||
4 | flushTests, | ||
5 | killallServers, | ||
6 | ServerInfo | ||
7 | } from '../../../../shared/utils' | ||
8 | import { runServer } from '../../../../shared/utils/server/servers' | ||
9 | |||
10 | describe('Start and stop server without web client routes', function () { | ||
11 | let server: ServerInfo | ||
12 | |||
13 | before(async function () { | ||
14 | this.timeout(30000) | ||
15 | |||
16 | await flushTests() | ||
17 | |||
18 | server = await runServer(1, {}, ['--no-client']) | ||
19 | }) | ||
20 | |||
21 | it('Should fail getting the client', function () { | ||
22 | const req = request(server.url) | ||
23 | .get('/') | ||
24 | |||
25 | return req.expect(404) | ||
26 | }) | ||
27 | |||
28 | after(async function () { | ||
29 | killallServers([ server ]) | ||
30 | |||
31 | // Keep the logs if the test failed | ||
32 | if (this['ok']) { | ||
33 | await flushTests() | ||
34 | } | ||
35 | }) | ||
36 | }) | ||
diff --git a/server/tests/api/server/reverse-proxy.ts b/server/tests/api/server/reverse-proxy.ts index e2c2a293e..ee0fffd5a 100644 --- a/server/tests/api/server/reverse-proxy.ts +++ b/server/tests/api/server/reverse-proxy.ts | |||
@@ -15,7 +15,7 @@ import { | |||
15 | userLogin, | 15 | userLogin, |
16 | viewVideo, | 16 | viewVideo, |
17 | wait | 17 | wait |
18 | } from '../../utils' | 18 | } from '../../../../shared/utils' |
19 | const expect = chai.expect | 19 | const expect = chai.expect |
20 | 20 | ||
21 | import { | 21 | import { |
@@ -23,7 +23,7 @@ import { | |||
23 | flushTests, | 23 | flushTests, |
24 | runServer, | 24 | runServer, |
25 | registerUser, getCustomConfig, setAccessTokensToServers, updateCustomConfig | 25 | registerUser, getCustomConfig, setAccessTokensToServers, updateCustomConfig |
26 | } from '../../utils/index' | 26 | } from '../../../../shared/utils/index' |
27 | 27 | ||
28 | describe('Test application behind a reverse proxy', function () { | 28 | describe('Test application behind a reverse proxy', function () { |
29 | let server = null | 29 | let server = null |
@@ -95,7 +95,7 @@ describe('Test application behind a reverse proxy', function () { | |||
95 | it('Should rate limit logins', async function () { | 95 | it('Should rate limit logins', async function () { |
96 | const user = { username: 'root', password: 'fail' } | 96 | const user = { username: 'root', password: 'fail' } |
97 | 97 | ||
98 | for (let i = 0; i < 14; i++) { | 98 | for (let i = 0; i < 19; i++) { |
99 | await userLogin(server, user, 400) | 99 | await userLogin(server, user, 400) |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts index cb229e876..aaa6c62f7 100644 --- a/server/tests/api/server/stats.ts +++ b/server/tests/api/server/stats.ts | |||
@@ -13,11 +13,11 @@ import { | |||
13 | uploadVideo, | 13 | uploadVideo, |
14 | viewVideo, | 14 | viewVideo, |
15 | wait | 15 | wait |
16 | } from '../../utils' | 16 | } from '../../../../shared/utils' |
17 | import { flushTests, setAccessTokensToServers } from '../../utils/index' | 17 | import { flushTests, setAccessTokensToServers } from '../../../../shared/utils/index' |
18 | import { getStats } from '../../utils/server/stats' | 18 | import { getStats } from '../../../../shared/utils/server/stats' |
19 | import { addVideoCommentThread } from '../../utils/videos/video-comments' | 19 | import { addVideoCommentThread } from '../../../../shared/utils/videos/video-comments' |
20 | import { waitJobs } from '../../utils/server/jobs' | 20 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
21 | 21 | ||
22 | const expect = chai.expect | 22 | const expect = chai.expect |
23 | 23 | ||
@@ -39,7 +39,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
39 | } | 39 | } |
40 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | 40 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) |
41 | 41 | ||
42 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, {}) | 42 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { fixture: 'video_short.webm' }) |
43 | const videoUUID = resVideo.body.video.uuid | 43 | const videoUUID = resVideo.body.video.uuid |
44 | 44 | ||
45 | await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment') | 45 | await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment') |
@@ -60,6 +60,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
60 | expect(data.totalLocalVideoComments).to.equal(1) | 60 | expect(data.totalLocalVideoComments).to.equal(1) |
61 | expect(data.totalLocalVideos).to.equal(1) | 61 | expect(data.totalLocalVideos).to.equal(1) |
62 | expect(data.totalLocalVideoViews).to.equal(1) | 62 | expect(data.totalLocalVideoViews).to.equal(1) |
63 | expect(data.totalLocalVideoFilesSize).to.equal(218910) | ||
63 | expect(data.totalUsers).to.equal(2) | 64 | expect(data.totalUsers).to.equal(2) |
64 | expect(data.totalVideoComments).to.equal(1) | 65 | expect(data.totalVideoComments).to.equal(1) |
65 | expect(data.totalVideos).to.equal(1) | 66 | expect(data.totalVideos).to.equal(1) |
@@ -74,6 +75,7 @@ describe('Test stats (excluding redundancy)', function () { | |||
74 | expect(data.totalLocalVideoComments).to.equal(0) | 75 | expect(data.totalLocalVideoComments).to.equal(0) |
75 | expect(data.totalLocalVideos).to.equal(0) | 76 | expect(data.totalLocalVideos).to.equal(0) |
76 | expect(data.totalLocalVideoViews).to.equal(0) | 77 | expect(data.totalLocalVideoViews).to.equal(0) |
78 | expect(data.totalLocalVideoFilesSize).to.equal(0) | ||
77 | expect(data.totalUsers).to.equal(1) | 79 | expect(data.totalUsers).to.equal(1) |
78 | expect(data.totalVideoComments).to.equal(1) | 80 | expect(data.totalVideoComments).to.equal(1) |
79 | expect(data.totalVideos).to.equal(1) | 81 | expect(data.totalVideos).to.equal(1) |
diff --git a/server/tests/api/server/tracker.ts b/server/tests/api/server/tracker.ts index 856f2f4d1..25ca00029 100644 --- a/server/tests/api/server/tracker.ts +++ b/server/tests/api/server/tracker.ts | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | import * as magnetUtil from 'magnet-uri' | 3 | import * as magnetUtil from 'magnet-uri' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { getVideo, killallServers, runServer, ServerInfo, uploadVideo } from '../../utils' | 5 | import { getVideo, killallServers, runServer, ServerInfo, uploadVideo } from '../../../../shared/utils' |
6 | import { flushTests, setAccessTokensToServers } from '../../utils/index' | 6 | import { flushTests, setAccessTokensToServers } from '../../../../shared/utils/index' |
7 | import { VideoDetails } from '../../../../shared/models/videos' | 7 | import { VideoDetails } from '../../../../shared/models/videos' |
8 | import * as WebTorrent from 'webtorrent' | 8 | import * as WebTorrent from 'webtorrent' |
9 | 9 | ||
diff --git a/server/tests/api/users/blocklist.ts b/server/tests/api/users/blocklist.ts new file mode 100644 index 000000000..4bca27a94 --- /dev/null +++ b/server/tests/api/users/blocklist.ts | |||
@@ -0,0 +1,511 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { AccountBlock, ServerBlock, Video } from '../../../../shared/index' | ||
6 | import { | ||
7 | createUser, | ||
8 | doubleFollow, | ||
9 | flushAndRunMultipleServers, | ||
10 | flushTests, | ||
11 | killallServers, | ||
12 | ServerInfo, | ||
13 | uploadVideo, | ||
14 | userLogin | ||
15 | } from '../../../../shared/utils/index' | ||
16 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' | ||
17 | import { getVideosListWithToken, getVideosList } from '../../../../shared/utils/videos/videos' | ||
18 | import { | ||
19 | addVideoCommentReply, | ||
20 | addVideoCommentThread, | ||
21 | getVideoCommentThreads, | ||
22 | getVideoThreadComments | ||
23 | } from '../../../../shared/utils/videos/video-comments' | ||
24 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
25 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | ||
26 | import { | ||
27 | addAccountToAccountBlocklist, | ||
28 | addAccountToServerBlocklist, | ||
29 | addServerToAccountBlocklist, | ||
30 | addServerToServerBlocklist, | ||
31 | getAccountBlocklistByAccount, | ||
32 | getAccountBlocklistByServer, | ||
33 | getServerBlocklistByAccount, | ||
34 | getServerBlocklistByServer, | ||
35 | removeAccountFromAccountBlocklist, | ||
36 | removeAccountFromServerBlocklist, | ||
37 | removeServerFromAccountBlocklist, | ||
38 | removeServerFromServerBlocklist | ||
39 | } from '../../../../shared/utils/users/blocklist' | ||
40 | |||
41 | const expect = chai.expect | ||
42 | |||
43 | async function checkAllVideos (url: string, token: string) { | ||
44 | { | ||
45 | const res = await getVideosListWithToken(url, token) | ||
46 | |||
47 | expect(res.body.data).to.have.lengthOf(4) | ||
48 | } | ||
49 | |||
50 | { | ||
51 | const res = await getVideosList(url) | ||
52 | |||
53 | expect(res.body.data).to.have.lengthOf(4) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | async function checkAllComments (url: string, token: string, videoUUID: string) { | ||
58 | const resThreads = await getVideoCommentThreads(url, videoUUID, 0, 5, '-createdAt', token) | ||
59 | |||
60 | const threads: VideoComment[] = resThreads.body.data | ||
61 | expect(threads).to.have.lengthOf(2) | ||
62 | |||
63 | for (const thread of threads) { | ||
64 | const res = await getVideoThreadComments(url, videoUUID, thread.id, token) | ||
65 | |||
66 | const tree: VideoCommentThreadTree = res.body | ||
67 | expect(tree.children).to.have.lengthOf(1) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | describe('Test blocklist', function () { | ||
72 | let servers: ServerInfo[] | ||
73 | let videoUUID1: string | ||
74 | let videoUUID2: string | ||
75 | let userToken1: string | ||
76 | let userModeratorToken: string | ||
77 | let userToken2: string | ||
78 | |||
79 | before(async function () { | ||
80 | this.timeout(60000) | ||
81 | |||
82 | await flushTests() | ||
83 | |||
84 | servers = await flushAndRunMultipleServers(2) | ||
85 | await setAccessTokensToServers(servers) | ||
86 | |||
87 | { | ||
88 | const user = { username: 'user1', password: 'password' } | ||
89 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | ||
90 | |||
91 | userToken1 = await userLogin(servers[0], user) | ||
92 | await uploadVideo(servers[0].url, userToken1, { name: 'video user 1' }) | ||
93 | } | ||
94 | |||
95 | { | ||
96 | const user = { username: 'moderator', password: 'password' } | ||
97 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password) | ||
98 | |||
99 | userModeratorToken = await userLogin(servers[0], user) | ||
100 | } | ||
101 | |||
102 | { | ||
103 | const user = { username: 'user2', password: 'password' } | ||
104 | await createUser(servers[1].url, servers[1].accessToken, user.username, user.password) | ||
105 | |||
106 | userToken2 = await userLogin(servers[1], user) | ||
107 | await uploadVideo(servers[1].url, userToken2, { name: 'video user 2' }) | ||
108 | } | ||
109 | |||
110 | { | ||
111 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video server 1' }) | ||
112 | videoUUID1 = res.body.video.uuid | ||
113 | } | ||
114 | |||
115 | { | ||
116 | const res = await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'video server 2' }) | ||
117 | videoUUID2 = res.body.video.uuid | ||
118 | } | ||
119 | |||
120 | await doubleFollow(servers[0], servers[1]) | ||
121 | |||
122 | { | ||
123 | const resComment = await addVideoCommentThread(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, 'comment root 1') | ||
124 | const resReply = await addVideoCommentReply(servers[ 0 ].url, userToken1, videoUUID1, resComment.body.comment.id, 'comment user 1') | ||
125 | await addVideoCommentReply(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, resReply.body.comment.id, 'comment root 1') | ||
126 | } | ||
127 | |||
128 | { | ||
129 | const resComment = await addVideoCommentThread(servers[ 0 ].url, userToken1, videoUUID1, 'comment user 1') | ||
130 | await addVideoCommentReply(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1, resComment.body.comment.id, 'comment root 1') | ||
131 | } | ||
132 | |||
133 | await waitJobs(servers) | ||
134 | }) | ||
135 | |||
136 | describe('User blocklist', function () { | ||
137 | |||
138 | describe('When managing account blocklist', function () { | ||
139 | it('Should list all videos', function () { | ||
140 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
141 | }) | ||
142 | |||
143 | it('Should list the comments', function () { | ||
144 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
145 | }) | ||
146 | |||
147 | it('Should block a remote account', async function () { | ||
148 | await addAccountToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
149 | }) | ||
150 | |||
151 | it('Should hide its videos', async function () { | ||
152 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
153 | |||
154 | const videos: Video[] = res.body.data | ||
155 | expect(videos).to.have.lengthOf(3) | ||
156 | |||
157 | const v = videos.find(v => v.name === 'video user 2') | ||
158 | expect(v).to.be.undefined | ||
159 | }) | ||
160 | |||
161 | it('Should block a local account', async function () { | ||
162 | await addAccountToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
163 | }) | ||
164 | |||
165 | it('Should hide its videos', async function () { | ||
166 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
167 | |||
168 | const videos: Video[] = res.body.data | ||
169 | expect(videos).to.have.lengthOf(2) | ||
170 | |||
171 | const v = videos.find(v => v.name === 'video user 1') | ||
172 | expect(v).to.be.undefined | ||
173 | }) | ||
174 | |||
175 | it('Should hide its comments', async function () { | ||
176 | const resThreads = await getVideoCommentThreads(servers[ 0 ].url, videoUUID1, 0, 5, '-createdAt', servers[ 0 ].accessToken) | ||
177 | |||
178 | const threads: VideoComment[] = resThreads.body.data | ||
179 | expect(threads).to.have.lengthOf(1) | ||
180 | expect(threads[ 0 ].totalReplies).to.equal(0) | ||
181 | |||
182 | const t = threads.find(t => t.text === 'comment user 1') | ||
183 | expect(t).to.be.undefined | ||
184 | |||
185 | for (const thread of threads) { | ||
186 | const res = await getVideoThreadComments(servers[ 0 ].url, videoUUID1, thread.id, servers[ 0 ].accessToken) | ||
187 | |||
188 | const tree: VideoCommentThreadTree = res.body | ||
189 | expect(tree.children).to.have.lengthOf(0) | ||
190 | } | ||
191 | }) | ||
192 | |||
193 | it('Should list all the videos with another user', async function () { | ||
194 | return checkAllVideos(servers[ 0 ].url, userToken1) | ||
195 | }) | ||
196 | |||
197 | it('Should list all the comments with another user', async function () { | ||
198 | return checkAllComments(servers[ 0 ].url, userToken1, videoUUID1) | ||
199 | }) | ||
200 | |||
201 | it('Should list blocked accounts', async function () { | ||
202 | { | ||
203 | const res = await getAccountBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
204 | const blocks: AccountBlock[] = res.body.data | ||
205 | |||
206 | expect(res.body.total).to.equal(2) | ||
207 | |||
208 | const block = blocks[ 0 ] | ||
209 | expect(block.byAccount.displayName).to.equal('root') | ||
210 | expect(block.byAccount.name).to.equal('root') | ||
211 | expect(block.blockedAccount.displayName).to.equal('user2') | ||
212 | expect(block.blockedAccount.name).to.equal('user2') | ||
213 | expect(block.blockedAccount.host).to.equal('localhost:9002') | ||
214 | } | ||
215 | |||
216 | { | ||
217 | const res = await getAccountBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 1, 2, 'createdAt') | ||
218 | const blocks: AccountBlock[] = res.body.data | ||
219 | |||
220 | expect(res.body.total).to.equal(2) | ||
221 | |||
222 | const block = blocks[ 0 ] | ||
223 | expect(block.byAccount.displayName).to.equal('root') | ||
224 | expect(block.byAccount.name).to.equal('root') | ||
225 | expect(block.blockedAccount.displayName).to.equal('user1') | ||
226 | expect(block.blockedAccount.name).to.equal('user1') | ||
227 | expect(block.blockedAccount.host).to.equal('localhost:9001') | ||
228 | } | ||
229 | }) | ||
230 | |||
231 | it('Should unblock the remote account', async function () { | ||
232 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
233 | }) | ||
234 | |||
235 | it('Should display its videos', async function () { | ||
236 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
237 | |||
238 | const videos: Video[] = res.body.data | ||
239 | expect(videos).to.have.lengthOf(3) | ||
240 | |||
241 | const v = videos.find(v => v.name === 'video user 2') | ||
242 | expect(v).not.to.be.undefined | ||
243 | }) | ||
244 | |||
245 | it('Should unblock the local account', async function () { | ||
246 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
247 | }) | ||
248 | |||
249 | it('Should display its comments', function () { | ||
250 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
251 | }) | ||
252 | }) | ||
253 | |||
254 | describe('When managing server blocklist', function () { | ||
255 | it('Should list all videos', function () { | ||
256 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
257 | }) | ||
258 | |||
259 | it('Should list the comments', function () { | ||
260 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
261 | }) | ||
262 | |||
263 | it('Should block a remote server', async function () { | ||
264 | await addServerToAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
265 | }) | ||
266 | |||
267 | it('Should hide its videos', async function () { | ||
268 | const res = await getVideosListWithToken(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
269 | |||
270 | const videos: Video[] = res.body.data | ||
271 | expect(videos).to.have.lengthOf(2) | ||
272 | |||
273 | const v1 = videos.find(v => v.name === 'video user 2') | ||
274 | const v2 = videos.find(v => v.name === 'video server 2') | ||
275 | |||
276 | expect(v1).to.be.undefined | ||
277 | expect(v2).to.be.undefined | ||
278 | }) | ||
279 | |||
280 | it('Should list all the videos with another user', async function () { | ||
281 | return checkAllVideos(servers[ 0 ].url, userToken1) | ||
282 | }) | ||
283 | |||
284 | it('Should hide its comments') | ||
285 | |||
286 | it('Should list blocked servers', async function () { | ||
287 | const res = await getServerBlocklistByAccount(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
288 | const blocks: ServerBlock[] = res.body.data | ||
289 | |||
290 | expect(res.body.total).to.equal(1) | ||
291 | |||
292 | const block = blocks[ 0 ] | ||
293 | expect(block.byAccount.displayName).to.equal('root') | ||
294 | expect(block.byAccount.name).to.equal('root') | ||
295 | expect(block.blockedServer.host).to.equal('localhost:9002') | ||
296 | }) | ||
297 | |||
298 | it('Should unblock the remote server', async function () { | ||
299 | await removeServerFromAccountBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
300 | }) | ||
301 | |||
302 | it('Should display its videos', function () { | ||
303 | return checkAllVideos(servers[ 0 ].url, servers[ 0 ].accessToken) | ||
304 | }) | ||
305 | |||
306 | it('Should display its comments', function () { | ||
307 | return checkAllComments(servers[ 0 ].url, servers[ 0 ].accessToken, videoUUID1) | ||
308 | }) | ||
309 | }) | ||
310 | }) | ||
311 | |||
312 | describe('Server blocklist', function () { | ||
313 | |||
314 | describe('When managing account blocklist', function () { | ||
315 | it('Should list all videos', async function () { | ||
316 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
317 | await checkAllVideos(servers[ 0 ].url, token) | ||
318 | } | ||
319 | }) | ||
320 | |||
321 | it('Should list the comments', async function () { | ||
322 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
323 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
324 | } | ||
325 | }) | ||
326 | |||
327 | it('Should block a remote account', async function () { | ||
328 | await addAccountToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
329 | }) | ||
330 | |||
331 | it('Should hide its videos', async function () { | ||
332 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
333 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
334 | |||
335 | const videos: Video[] = res.body.data | ||
336 | expect(videos).to.have.lengthOf(3) | ||
337 | |||
338 | const v = videos.find(v => v.name === 'video user 2') | ||
339 | expect(v).to.be.undefined | ||
340 | } | ||
341 | }) | ||
342 | |||
343 | it('Should block a local account', async function () { | ||
344 | await addAccountToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
345 | }) | ||
346 | |||
347 | it('Should hide its videos', async function () { | ||
348 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
349 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
350 | |||
351 | const videos: Video[] = res.body.data | ||
352 | expect(videos).to.have.lengthOf(2) | ||
353 | |||
354 | const v = videos.find(v => v.name === 'video user 1') | ||
355 | expect(v).to.be.undefined | ||
356 | } | ||
357 | }) | ||
358 | |||
359 | it('Should hide its comments', async function () { | ||
360 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
361 | const resThreads = await getVideoCommentThreads(servers[ 0 ].url, videoUUID1, 0, 5, '-createdAt', token) | ||
362 | |||
363 | const threads: VideoComment[] = resThreads.body.data | ||
364 | expect(threads).to.have.lengthOf(1) | ||
365 | expect(threads[ 0 ].totalReplies).to.equal(0) | ||
366 | |||
367 | const t = threads.find(t => t.text === 'comment user 1') | ||
368 | expect(t).to.be.undefined | ||
369 | |||
370 | for (const thread of threads) { | ||
371 | const res = await getVideoThreadComments(servers[ 0 ].url, videoUUID1, thread.id, token) | ||
372 | |||
373 | const tree: VideoCommentThreadTree = res.body | ||
374 | expect(tree.children).to.have.lengthOf(0) | ||
375 | } | ||
376 | } | ||
377 | }) | ||
378 | |||
379 | it('Should list blocked accounts', async function () { | ||
380 | { | ||
381 | const res = await getAccountBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
382 | const blocks: AccountBlock[] = res.body.data | ||
383 | |||
384 | expect(res.body.total).to.equal(2) | ||
385 | |||
386 | const block = blocks[ 0 ] | ||
387 | expect(block.byAccount.displayName).to.equal('peertube') | ||
388 | expect(block.byAccount.name).to.equal('peertube') | ||
389 | expect(block.blockedAccount.displayName).to.equal('user2') | ||
390 | expect(block.blockedAccount.name).to.equal('user2') | ||
391 | expect(block.blockedAccount.host).to.equal('localhost:9002') | ||
392 | } | ||
393 | |||
394 | { | ||
395 | const res = await getAccountBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 1, 2, 'createdAt') | ||
396 | const blocks: AccountBlock[] = res.body.data | ||
397 | |||
398 | expect(res.body.total).to.equal(2) | ||
399 | |||
400 | const block = blocks[ 0 ] | ||
401 | expect(block.byAccount.displayName).to.equal('peertube') | ||
402 | expect(block.byAccount.name).to.equal('peertube') | ||
403 | expect(block.blockedAccount.displayName).to.equal('user1') | ||
404 | expect(block.blockedAccount.name).to.equal('user1') | ||
405 | expect(block.blockedAccount.host).to.equal('localhost:9001') | ||
406 | } | ||
407 | }) | ||
408 | |||
409 | it('Should unblock the remote account', async function () { | ||
410 | await removeAccountFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user2@localhost:9002') | ||
411 | }) | ||
412 | |||
413 | it('Should display its videos', async function () { | ||
414 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
415 | const res = await getVideosListWithToken(servers[ 0 ].url, token) | ||
416 | |||
417 | const videos: Video[] = res.body.data | ||
418 | expect(videos).to.have.lengthOf(3) | ||
419 | |||
420 | const v = videos.find(v => v.name === 'video user 2') | ||
421 | expect(v).not.to.be.undefined | ||
422 | } | ||
423 | }) | ||
424 | |||
425 | it('Should unblock the local account', async function () { | ||
426 | await removeAccountFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'user1') | ||
427 | }) | ||
428 | |||
429 | it('Should display its comments', async function () { | ||
430 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
431 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
432 | } | ||
433 | }) | ||
434 | }) | ||
435 | |||
436 | describe('When managing server blocklist', function () { | ||
437 | it('Should list all videos', async function () { | ||
438 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
439 | await checkAllVideos(servers[ 0 ].url, token) | ||
440 | } | ||
441 | }) | ||
442 | |||
443 | it('Should list the comments', async function () { | ||
444 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
445 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
446 | } | ||
447 | }) | ||
448 | |||
449 | it('Should block a remote server', async function () { | ||
450 | await addServerToServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
451 | }) | ||
452 | |||
453 | it('Should hide its videos', async function () { | ||
454 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
455 | const res1 = await getVideosList(servers[ 0 ].url) | ||
456 | const res2 = await getVideosListWithToken(servers[ 0 ].url, token) | ||
457 | |||
458 | for (const res of [ res1, res2 ]) { | ||
459 | const videos: Video[] = res.body.data | ||
460 | expect(videos).to.have.lengthOf(2) | ||
461 | |||
462 | const v1 = videos.find(v => v.name === 'video user 2') | ||
463 | const v2 = videos.find(v => v.name === 'video server 2') | ||
464 | |||
465 | expect(v1).to.be.undefined | ||
466 | expect(v2).to.be.undefined | ||
467 | } | ||
468 | } | ||
469 | }) | ||
470 | |||
471 | it('Should hide its comments') | ||
472 | |||
473 | it('Should list blocked servers', async function () { | ||
474 | const res = await getServerBlocklistByServer(servers[ 0 ].url, servers[ 0 ].accessToken, 0, 1, 'createdAt') | ||
475 | const blocks: ServerBlock[] = res.body.data | ||
476 | |||
477 | expect(res.body.total).to.equal(1) | ||
478 | |||
479 | const block = blocks[ 0 ] | ||
480 | expect(block.byAccount.displayName).to.equal('peertube') | ||
481 | expect(block.byAccount.name).to.equal('peertube') | ||
482 | expect(block.blockedServer.host).to.equal('localhost:9002') | ||
483 | }) | ||
484 | |||
485 | it('Should unblock the remote server', async function () { | ||
486 | await removeServerFromServerBlocklist(servers[ 0 ].url, servers[ 0 ].accessToken, 'localhost:9002') | ||
487 | }) | ||
488 | |||
489 | it('Should list all videos', async function () { | ||
490 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
491 | await checkAllVideos(servers[ 0 ].url, token) | ||
492 | } | ||
493 | }) | ||
494 | |||
495 | it('Should list the comments', async function () { | ||
496 | for (const token of [ userModeratorToken, servers[ 0 ].accessToken ]) { | ||
497 | await checkAllComments(servers[ 0 ].url, token, videoUUID1) | ||
498 | } | ||
499 | }) | ||
500 | }) | ||
501 | }) | ||
502 | |||
503 | after(async function () { | ||
504 | killallServers(servers) | ||
505 | |||
506 | // Keep the logs if the test failed | ||
507 | if (this[ 'ok' ]) { | ||
508 | await flushTests() | ||
509 | } | ||
510 | }) | ||
511 | }) | ||
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts index 21d75da3e..52ba6984e 100644 --- a/server/tests/api/users/index.ts +++ b/server/tests/api/users/index.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import './users-verification' | ||
2 | import './user-notifications' | ||
3 | import './blocklist' | ||
1 | import './user-subscriptions' | 4 | import './user-subscriptions' |
2 | import './users' | 5 | import './users' |
3 | import './users-verification' | ||
4 | import './users-multiple-servers' | 6 | import './users-multiple-servers' |
diff --git a/server/tests/api/users/user-notifications.ts b/server/tests/api/users/user-notifications.ts new file mode 100644 index 000000000..69e51677e --- /dev/null +++ b/server/tests/api/users/user-notifications.ts | |||
@@ -0,0 +1,1053 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | addVideoToBlacklist, | ||
7 | createUser, | ||
8 | doubleFollow, | ||
9 | flushAndRunMultipleServers, | ||
10 | flushTests, | ||
11 | getMyUserInformation, | ||
12 | immutableAssign, | ||
13 | registerUser, | ||
14 | removeVideoFromBlacklist, | ||
15 | reportVideoAbuse, | ||
16 | updateMyUser, | ||
17 | updateVideo, | ||
18 | updateVideoChannel, | ||
19 | userLogin, | ||
20 | wait | ||
21 | } from '../../../../shared/utils' | ||
22 | import { killallServers, ServerInfo, uploadVideo } from '../../../../shared/utils/index' | ||
23 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' | ||
24 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
25 | import { getUserNotificationSocket } from '../../../../shared/utils/socket/socket-io' | ||
26 | import { | ||
27 | checkCommentMention, | ||
28 | CheckerBaseParams, | ||
29 | checkMyVideoImportIsFinished, | ||
30 | checkNewActorFollow, | ||
31 | checkNewBlacklistOnMyVideo, | ||
32 | checkNewCommentOnMyVideo, | ||
33 | checkNewVideoAbuseForModerators, | ||
34 | checkNewVideoFromSubscription, | ||
35 | checkUserRegistered, | ||
36 | checkVideoIsPublished, | ||
37 | getLastNotification, | ||
38 | getUserNotifications, | ||
39 | markAsReadNotifications, | ||
40 | updateMyNotificationSettings, | ||
41 | markAsReadAllNotifications | ||
42 | } from '../../../../shared/utils/users/user-notifications' | ||
43 | import { | ||
44 | User, | ||
45 | UserNotification, | ||
46 | UserNotificationSetting, | ||
47 | UserNotificationSettingValue, | ||
48 | UserNotificationType | ||
49 | } from '../../../../shared/models/users' | ||
50 | import { MockSmtpServer } from '../../../../shared/utils/miscs/email' | ||
51 | import { addUserSubscription, removeUserSubscription } from '../../../../shared/utils/users/user-subscriptions' | ||
52 | import { VideoPrivacy } from '../../../../shared/models/videos' | ||
53 | import { getBadVideoUrl, getYoutubeVideoUrl, importVideo } from '../../../../shared/utils/videos/video-imports' | ||
54 | import { addVideoCommentReply, addVideoCommentThread } from '../../../../shared/utils/videos/video-comments' | ||
55 | import * as uuidv4 from 'uuid/v4' | ||
56 | import { addAccountToAccountBlocklist, removeAccountFromAccountBlocklist } from '../../../../shared/utils/users/blocklist' | ||
57 | |||
58 | const expect = chai.expect | ||
59 | |||
60 | async function uploadVideoByRemoteAccount (servers: ServerInfo[], additionalParams: any = {}) { | ||
61 | const name = 'remote video ' + uuidv4() | ||
62 | |||
63 | const data = Object.assign({ name }, additionalParams) | ||
64 | const res = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, data) | ||
65 | |||
66 | await waitJobs(servers) | ||
67 | |||
68 | return { uuid: res.body.video.uuid, name } | ||
69 | } | ||
70 | |||
71 | async function uploadVideoByLocalAccount (servers: ServerInfo[], additionalParams: any = {}) { | ||
72 | const name = 'local video ' + uuidv4() | ||
73 | |||
74 | const data = Object.assign({ name }, additionalParams) | ||
75 | const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, data) | ||
76 | |||
77 | await waitJobs(servers) | ||
78 | |||
79 | return { uuid: res.body.video.uuid, name } | ||
80 | } | ||
81 | |||
82 | describe('Test users notifications', function () { | ||
83 | let servers: ServerInfo[] = [] | ||
84 | let userAccessToken: string | ||
85 | let userNotifications: UserNotification[] = [] | ||
86 | let adminNotifications: UserNotification[] = [] | ||
87 | let adminNotificationsServer2: UserNotification[] = [] | ||
88 | const emails: object[] = [] | ||
89 | let channelId: number | ||
90 | |||
91 | const allNotificationSettings: UserNotificationSetting = { | ||
92 | newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
93 | newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
94 | videoAbuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
95 | blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
96 | myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
97 | myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
98 | commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
99 | newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL, | ||
100 | newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL | ||
101 | } | ||
102 | |||
103 | before(async function () { | ||
104 | this.timeout(120000) | ||
105 | |||
106 | await MockSmtpServer.Instance.collectEmails(emails) | ||
107 | |||
108 | await flushTests() | ||
109 | |||
110 | const overrideConfig = { | ||
111 | smtp: { | ||
112 | hostname: 'localhost' | ||
113 | } | ||
114 | } | ||
115 | servers = await flushAndRunMultipleServers(2, overrideConfig) | ||
116 | |||
117 | // Get the access tokens | ||
118 | await setAccessTokensToServers(servers) | ||
119 | |||
120 | // Server 1 and server 2 follow each other | ||
121 | await doubleFollow(servers[0], servers[1]) | ||
122 | |||
123 | await waitJobs(servers) | ||
124 | |||
125 | const user = { | ||
126 | username: 'user_1', | ||
127 | password: 'super password' | ||
128 | } | ||
129 | await createUser(servers[0].url, servers[0].accessToken, user.username, user.password, 10 * 1000 * 1000) | ||
130 | userAccessToken = await userLogin(servers[0], user) | ||
131 | |||
132 | await updateMyNotificationSettings(servers[0].url, userAccessToken, allNotificationSettings) | ||
133 | await updateMyNotificationSettings(servers[0].url, servers[0].accessToken, allNotificationSettings) | ||
134 | await updateMyNotificationSettings(servers[1].url, servers[1].accessToken, allNotificationSettings) | ||
135 | |||
136 | { | ||
137 | const socket = getUserNotificationSocket(servers[ 0 ].url, userAccessToken) | ||
138 | socket.on('new-notification', n => userNotifications.push(n)) | ||
139 | } | ||
140 | { | ||
141 | const socket = getUserNotificationSocket(servers[ 0 ].url, servers[0].accessToken) | ||
142 | socket.on('new-notification', n => adminNotifications.push(n)) | ||
143 | } | ||
144 | { | ||
145 | const socket = getUserNotificationSocket(servers[ 1 ].url, servers[1].accessToken) | ||
146 | socket.on('new-notification', n => adminNotificationsServer2.push(n)) | ||
147 | } | ||
148 | |||
149 | { | ||
150 | const resChannel = await getMyUserInformation(servers[0].url, servers[0].accessToken) | ||
151 | channelId = resChannel.body.videoChannels[0].id | ||
152 | } | ||
153 | }) | ||
154 | |||
155 | describe('New video from my subscription notification', function () { | ||
156 | let baseParams: CheckerBaseParams | ||
157 | |||
158 | before(() => { | ||
159 | baseParams = { | ||
160 | server: servers[0], | ||
161 | emails, | ||
162 | socketNotifications: userNotifications, | ||
163 | token: userAccessToken | ||
164 | } | ||
165 | }) | ||
166 | |||
167 | it('Should not send notifications if the user does not follow the video publisher', async function () { | ||
168 | this.timeout(10000) | ||
169 | |||
170 | await uploadVideoByLocalAccount(servers) | ||
171 | |||
172 | const notification = await getLastNotification(servers[ 0 ].url, userAccessToken) | ||
173 | expect(notification).to.be.undefined | ||
174 | |||
175 | expect(emails).to.have.lengthOf(0) | ||
176 | expect(userNotifications).to.have.lengthOf(0) | ||
177 | }) | ||
178 | |||
179 | it('Should send a new video notification if the user follows the local video publisher', async function () { | ||
180 | this.timeout(15000) | ||
181 | |||
182 | await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:9001') | ||
183 | await waitJobs(servers) | ||
184 | |||
185 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
186 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
187 | }) | ||
188 | |||
189 | it('Should send a new video notification from a remote account', async function () { | ||
190 | this.timeout(50000) // Server 2 has transcoding enabled | ||
191 | |||
192 | await addUserSubscription(servers[0].url, userAccessToken, 'root_channel@localhost:9002') | ||
193 | await waitJobs(servers) | ||
194 | |||
195 | const { name, uuid } = await uploadVideoByRemoteAccount(servers) | ||
196 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
197 | }) | ||
198 | |||
199 | it('Should send a new video notification on a scheduled publication', async function () { | ||
200 | this.timeout(20000) | ||
201 | |||
202 | // In 2 seconds | ||
203 | let updateAt = new Date(new Date().getTime() + 2000) | ||
204 | |||
205 | const data = { | ||
206 | privacy: VideoPrivacy.PRIVATE, | ||
207 | scheduleUpdate: { | ||
208 | updateAt: updateAt.toISOString(), | ||
209 | privacy: VideoPrivacy.PUBLIC | ||
210 | } | ||
211 | } | ||
212 | const { name, uuid } = await uploadVideoByLocalAccount(servers, data) | ||
213 | |||
214 | await wait(6000) | ||
215 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
216 | }) | ||
217 | |||
218 | it('Should send a new video notification on a remote scheduled publication', async function () { | ||
219 | this.timeout(20000) | ||
220 | |||
221 | // In 2 seconds | ||
222 | let updateAt = new Date(new Date().getTime() + 2000) | ||
223 | |||
224 | const data = { | ||
225 | privacy: VideoPrivacy.PRIVATE, | ||
226 | scheduleUpdate: { | ||
227 | updateAt: updateAt.toISOString(), | ||
228 | privacy: VideoPrivacy.PUBLIC | ||
229 | } | ||
230 | } | ||
231 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, data) | ||
232 | await waitJobs(servers) | ||
233 | |||
234 | await wait(6000) | ||
235 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
236 | }) | ||
237 | |||
238 | it('Should not send a notification before the video is published', async function () { | ||
239 | this.timeout(20000) | ||
240 | |||
241 | let updateAt = new Date(new Date().getTime() + 100000) | ||
242 | |||
243 | const data = { | ||
244 | privacy: VideoPrivacy.PRIVATE, | ||
245 | scheduleUpdate: { | ||
246 | updateAt: updateAt.toISOString(), | ||
247 | privacy: VideoPrivacy.PUBLIC | ||
248 | } | ||
249 | } | ||
250 | const { name, uuid } = await uploadVideoByLocalAccount(servers, data) | ||
251 | |||
252 | await wait(6000) | ||
253 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence') | ||
254 | }) | ||
255 | |||
256 | it('Should send a new video notification when a video becomes public', async function () { | ||
257 | this.timeout(10000) | ||
258 | |||
259 | const data = { privacy: VideoPrivacy.PRIVATE } | ||
260 | const { name, uuid } = await uploadVideoByLocalAccount(servers, data) | ||
261 | |||
262 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence') | ||
263 | |||
264 | await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC }) | ||
265 | |||
266 | await wait(500) | ||
267 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
268 | }) | ||
269 | |||
270 | it('Should send a new video notification when a remote video becomes public', async function () { | ||
271 | this.timeout(20000) | ||
272 | |||
273 | const data = { privacy: VideoPrivacy.PRIVATE } | ||
274 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, data) | ||
275 | |||
276 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence') | ||
277 | |||
278 | await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.PUBLIC }) | ||
279 | |||
280 | await waitJobs(servers) | ||
281 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
282 | }) | ||
283 | |||
284 | it('Should not send a new video notification when a video becomes unlisted', async function () { | ||
285 | this.timeout(20000) | ||
286 | |||
287 | const data = { privacy: VideoPrivacy.PRIVATE } | ||
288 | const { name, uuid } = await uploadVideoByLocalAccount(servers, data) | ||
289 | |||
290 | await updateVideo(servers[0].url, servers[0].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED }) | ||
291 | |||
292 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence') | ||
293 | }) | ||
294 | |||
295 | it('Should not send a new video notification when a remote video becomes unlisted', async function () { | ||
296 | this.timeout(20000) | ||
297 | |||
298 | const data = { privacy: VideoPrivacy.PRIVATE } | ||
299 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, data) | ||
300 | |||
301 | await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED }) | ||
302 | |||
303 | await waitJobs(servers) | ||
304 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'absence') | ||
305 | }) | ||
306 | |||
307 | it('Should send a new video notification after a video import', async function () { | ||
308 | this.timeout(30000) | ||
309 | |||
310 | const name = 'video import ' + uuidv4() | ||
311 | |||
312 | const attributes = { | ||
313 | name, | ||
314 | channelId, | ||
315 | privacy: VideoPrivacy.PUBLIC, | ||
316 | targetUrl: getYoutubeVideoUrl() | ||
317 | } | ||
318 | const res = await importVideo(servers[0].url, servers[0].accessToken, attributes) | ||
319 | const uuid = res.body.video.uuid | ||
320 | |||
321 | await waitJobs(servers) | ||
322 | |||
323 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
324 | }) | ||
325 | }) | ||
326 | |||
327 | describe('Comment on my video notifications', function () { | ||
328 | let baseParams: CheckerBaseParams | ||
329 | |||
330 | before(() => { | ||
331 | baseParams = { | ||
332 | server: servers[0], | ||
333 | emails, | ||
334 | socketNotifications: userNotifications, | ||
335 | token: userAccessToken | ||
336 | } | ||
337 | }) | ||
338 | |||
339 | it('Should not send a new comment notification after a comment on another video', async function () { | ||
340 | this.timeout(10000) | ||
341 | |||
342 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' }) | ||
343 | const uuid = resVideo.body.video.uuid | ||
344 | |||
345 | const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment') | ||
346 | const commentId = resComment.body.comment.id | ||
347 | |||
348 | await wait(500) | ||
349 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence') | ||
350 | }) | ||
351 | |||
352 | it('Should not send a new comment notification if I comment my own video', async function () { | ||
353 | this.timeout(10000) | ||
354 | |||
355 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
356 | const uuid = resVideo.body.video.uuid | ||
357 | |||
358 | const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, uuid, 'comment') | ||
359 | const commentId = resComment.body.comment.id | ||
360 | |||
361 | await wait(500) | ||
362 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence') | ||
363 | }) | ||
364 | |||
365 | it('Should not send a new comment notification if the account is muted', async function () { | ||
366 | this.timeout(10000) | ||
367 | |||
368 | await addAccountToAccountBlocklist(servers[ 0 ].url, userAccessToken, 'root') | ||
369 | |||
370 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
371 | const uuid = resVideo.body.video.uuid | ||
372 | |||
373 | const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment') | ||
374 | const commentId = resComment.body.comment.id | ||
375 | |||
376 | await wait(500) | ||
377 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'absence') | ||
378 | |||
379 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, userAccessToken, 'root') | ||
380 | }) | ||
381 | |||
382 | it('Should send a new comment notification after a local comment on my video', async function () { | ||
383 | this.timeout(10000) | ||
384 | |||
385 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
386 | const uuid = resVideo.body.video.uuid | ||
387 | |||
388 | const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment') | ||
389 | const commentId = resComment.body.comment.id | ||
390 | |||
391 | await wait(500) | ||
392 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence') | ||
393 | }) | ||
394 | |||
395 | it('Should send a new comment notification after a remote comment on my video', async function () { | ||
396 | this.timeout(10000) | ||
397 | |||
398 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
399 | const uuid = resVideo.body.video.uuid | ||
400 | |||
401 | await waitJobs(servers) | ||
402 | |||
403 | const resComment = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment') | ||
404 | const commentId = resComment.body.comment.id | ||
405 | |||
406 | await waitJobs(servers) | ||
407 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, commentId, 'presence') | ||
408 | }) | ||
409 | |||
410 | it('Should send a new comment notification after a local reply on my video', async function () { | ||
411 | this.timeout(10000) | ||
412 | |||
413 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
414 | const uuid = resVideo.body.video.uuid | ||
415 | |||
416 | const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, 'comment') | ||
417 | const threadId = resThread.body.comment.id | ||
418 | |||
419 | const resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, 'reply') | ||
420 | const commentId = resComment.body.comment.id | ||
421 | |||
422 | await wait(500) | ||
423 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence') | ||
424 | }) | ||
425 | |||
426 | it('Should send a new comment notification after a remote reply on my video', async function () { | ||
427 | this.timeout(10000) | ||
428 | |||
429 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
430 | const uuid = resVideo.body.video.uuid | ||
431 | await waitJobs(servers) | ||
432 | |||
433 | const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'comment') | ||
434 | const threadId = resThread.body.comment.id | ||
435 | |||
436 | const resComment = await addVideoCommentReply(servers[1].url, servers[1].accessToken, uuid, threadId, 'reply') | ||
437 | const commentId = resComment.body.comment.id | ||
438 | |||
439 | await waitJobs(servers) | ||
440 | await checkNewCommentOnMyVideo(baseParams, uuid, commentId, threadId, 'presence') | ||
441 | }) | ||
442 | }) | ||
443 | |||
444 | describe('Mention notifications', function () { | ||
445 | let baseParams: CheckerBaseParams | ||
446 | |||
447 | before(async () => { | ||
448 | baseParams = { | ||
449 | server: servers[0], | ||
450 | emails, | ||
451 | socketNotifications: userNotifications, | ||
452 | token: userAccessToken | ||
453 | } | ||
454 | |||
455 | await updateMyUser({ | ||
456 | url: servers[0].url, | ||
457 | accessToken: servers[0].accessToken, | ||
458 | displayName: 'super root name' | ||
459 | }) | ||
460 | |||
461 | await updateMyUser({ | ||
462 | url: servers[1].url, | ||
463 | accessToken: servers[1].accessToken, | ||
464 | displayName: 'super root 2 name' | ||
465 | }) | ||
466 | }) | ||
467 | |||
468 | it('Should not send a new mention comment notification if I mention the video owner', async function () { | ||
469 | this.timeout(10000) | ||
470 | |||
471 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name: 'super video' }) | ||
472 | const uuid = resVideo.body.video.uuid | ||
473 | |||
474 | const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello') | ||
475 | const commentId = resComment.body.comment.id | ||
476 | |||
477 | await wait(500) | ||
478 | await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence') | ||
479 | }) | ||
480 | |||
481 | it('Should not send a new mention comment notification if I mention myself', async function () { | ||
482 | this.timeout(10000) | ||
483 | |||
484 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' }) | ||
485 | const uuid = resVideo.body.video.uuid | ||
486 | |||
487 | const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, uuid, '@user_1 hello') | ||
488 | const commentId = resComment.body.comment.id | ||
489 | |||
490 | await wait(500) | ||
491 | await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence') | ||
492 | }) | ||
493 | |||
494 | it('Should not send a new mention notification if the account is muted', async function () { | ||
495 | this.timeout(10000) | ||
496 | |||
497 | await addAccountToAccountBlocklist(servers[ 0 ].url, userAccessToken, 'root') | ||
498 | |||
499 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' }) | ||
500 | const uuid = resVideo.body.video.uuid | ||
501 | |||
502 | const resComment = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello') | ||
503 | const commentId = resComment.body.comment.id | ||
504 | |||
505 | await wait(500) | ||
506 | await checkCommentMention(baseParams, uuid, commentId, commentId, 'super root name', 'absence') | ||
507 | |||
508 | await removeAccountFromAccountBlocklist(servers[ 0 ].url, userAccessToken, 'root') | ||
509 | }) | ||
510 | |||
511 | it('Should send a new mention notification after local comments', async function () { | ||
512 | this.timeout(10000) | ||
513 | |||
514 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' }) | ||
515 | const uuid = resVideo.body.video.uuid | ||
516 | |||
517 | const resThread = await addVideoCommentThread(servers[0].url, servers[0].accessToken, uuid, '@user_1 hello 1') | ||
518 | const threadId = resThread.body.comment.id | ||
519 | |||
520 | await wait(500) | ||
521 | await checkCommentMention(baseParams, uuid, threadId, threadId, 'super root name', 'presence') | ||
522 | |||
523 | const resComment = await addVideoCommentReply(servers[0].url, servers[0].accessToken, uuid, threadId, 'hello 2 @user_1') | ||
524 | const commentId = resComment.body.comment.id | ||
525 | |||
526 | await wait(500) | ||
527 | await checkCommentMention(baseParams, uuid, commentId, threadId, 'super root name', 'presence') | ||
528 | }) | ||
529 | |||
530 | it('Should send a new mention notification after remote comments', async function () { | ||
531 | this.timeout(20000) | ||
532 | |||
533 | const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' }) | ||
534 | const uuid = resVideo.body.video.uuid | ||
535 | |||
536 | await waitJobs(servers) | ||
537 | const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, 'hello @user_1@localhost:9001 1') | ||
538 | const threadId = resThread.body.comment.id | ||
539 | |||
540 | await waitJobs(servers) | ||
541 | await checkCommentMention(baseParams, uuid, threadId, threadId, 'super root 2 name', 'presence') | ||
542 | |||
543 | const text = '@user_1@localhost:9001 hello 2 @root@localhost:9001' | ||
544 | const resComment = await addVideoCommentReply(servers[1].url, servers[1].accessToken, uuid, threadId, text) | ||
545 | const commentId = resComment.body.comment.id | ||
546 | |||
547 | await waitJobs(servers) | ||
548 | await checkCommentMention(baseParams, uuid, commentId, threadId, 'super root 2 name', 'presence') | ||
549 | }) | ||
550 | }) | ||
551 | |||
552 | describe('Video abuse for moderators notification' , function () { | ||
553 | let baseParams: CheckerBaseParams | ||
554 | |||
555 | before(() => { | ||
556 | baseParams = { | ||
557 | server: servers[0], | ||
558 | emails, | ||
559 | socketNotifications: adminNotifications, | ||
560 | token: servers[0].accessToken | ||
561 | } | ||
562 | }) | ||
563 | |||
564 | it('Should send a notification to moderators on local video abuse', async function () { | ||
565 | this.timeout(10000) | ||
566 | |||
567 | const name = 'video for abuse ' + uuidv4() | ||
568 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name }) | ||
569 | const uuid = resVideo.body.video.uuid | ||
570 | |||
571 | await reportVideoAbuse(servers[0].url, servers[0].accessToken, uuid, 'super reason') | ||
572 | |||
573 | await waitJobs(servers) | ||
574 | await checkNewVideoAbuseForModerators(baseParams, uuid, name, 'presence') | ||
575 | }) | ||
576 | |||
577 | it('Should send a notification to moderators on remote video abuse', async function () { | ||
578 | this.timeout(10000) | ||
579 | |||
580 | const name = 'video for abuse ' + uuidv4() | ||
581 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name }) | ||
582 | const uuid = resVideo.body.video.uuid | ||
583 | |||
584 | await waitJobs(servers) | ||
585 | |||
586 | await reportVideoAbuse(servers[1].url, servers[1].accessToken, uuid, 'super reason') | ||
587 | |||
588 | await waitJobs(servers) | ||
589 | await checkNewVideoAbuseForModerators(baseParams, uuid, name, 'presence') | ||
590 | }) | ||
591 | }) | ||
592 | |||
593 | describe('Video blacklist on my video', function () { | ||
594 | let baseParams: CheckerBaseParams | ||
595 | |||
596 | before(() => { | ||
597 | baseParams = { | ||
598 | server: servers[0], | ||
599 | emails, | ||
600 | socketNotifications: userNotifications, | ||
601 | token: userAccessToken | ||
602 | } | ||
603 | }) | ||
604 | |||
605 | it('Should send a notification to video owner on blacklist', async function () { | ||
606 | this.timeout(10000) | ||
607 | |||
608 | const name = 'video for abuse ' + uuidv4() | ||
609 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name }) | ||
610 | const uuid = resVideo.body.video.uuid | ||
611 | |||
612 | await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid) | ||
613 | |||
614 | await waitJobs(servers) | ||
615 | await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'blacklist') | ||
616 | }) | ||
617 | |||
618 | it('Should send a notification to video owner on unblacklist', async function () { | ||
619 | this.timeout(10000) | ||
620 | |||
621 | const name = 'video for abuse ' + uuidv4() | ||
622 | const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name }) | ||
623 | const uuid = resVideo.body.video.uuid | ||
624 | |||
625 | await addVideoToBlacklist(servers[0].url, servers[0].accessToken, uuid) | ||
626 | |||
627 | await waitJobs(servers) | ||
628 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, uuid) | ||
629 | await waitJobs(servers) | ||
630 | |||
631 | await wait(500) | ||
632 | await checkNewBlacklistOnMyVideo(baseParams, uuid, name, 'unblacklist') | ||
633 | }) | ||
634 | }) | ||
635 | |||
636 | describe('My video is published', function () { | ||
637 | let baseParams: CheckerBaseParams | ||
638 | |||
639 | before(() => { | ||
640 | baseParams = { | ||
641 | server: servers[1], | ||
642 | emails, | ||
643 | socketNotifications: adminNotificationsServer2, | ||
644 | token: servers[1].accessToken | ||
645 | } | ||
646 | }) | ||
647 | |||
648 | it('Should not send a notification if transcoding is not enabled', async function () { | ||
649 | this.timeout(10000) | ||
650 | |||
651 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
652 | await waitJobs(servers) | ||
653 | |||
654 | await checkVideoIsPublished(baseParams, name, uuid, 'absence') | ||
655 | }) | ||
656 | |||
657 | it('Should not send a notification if the wait transcoding is false', async function () { | ||
658 | this.timeout(50000) | ||
659 | |||
660 | await uploadVideoByRemoteAccount(servers, { waitTranscoding: false }) | ||
661 | await waitJobs(servers) | ||
662 | |||
663 | const notification = await getLastNotification(servers[ 0 ].url, userAccessToken) | ||
664 | if (notification) { | ||
665 | expect(notification.type).to.not.equal(UserNotificationType.MY_VIDEO_PUBLISHED) | ||
666 | } | ||
667 | }) | ||
668 | |||
669 | it('Should send a notification even if the video is not transcoded in other resolutions', async function () { | ||
670 | this.timeout(50000) | ||
671 | |||
672 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, { waitTranscoding: true, fixture: 'video_short_240p.mp4' }) | ||
673 | await waitJobs(servers) | ||
674 | |||
675 | await checkVideoIsPublished(baseParams, name, uuid, 'presence') | ||
676 | }) | ||
677 | |||
678 | it('Should send a notification with a transcoded video', async function () { | ||
679 | this.timeout(50000) | ||
680 | |||
681 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, { waitTranscoding: true }) | ||
682 | await waitJobs(servers) | ||
683 | |||
684 | await checkVideoIsPublished(baseParams, name, uuid, 'presence') | ||
685 | }) | ||
686 | |||
687 | it('Should send a notification when an imported video is transcoded', async function () { | ||
688 | this.timeout(50000) | ||
689 | |||
690 | const name = 'video import ' + uuidv4() | ||
691 | |||
692 | const attributes = { | ||
693 | name, | ||
694 | channelId, | ||
695 | privacy: VideoPrivacy.PUBLIC, | ||
696 | targetUrl: getYoutubeVideoUrl(), | ||
697 | waitTranscoding: true | ||
698 | } | ||
699 | const res = await importVideo(servers[1].url, servers[1].accessToken, attributes) | ||
700 | const uuid = res.body.video.uuid | ||
701 | |||
702 | await waitJobs(servers) | ||
703 | await checkVideoIsPublished(baseParams, name, uuid, 'presence') | ||
704 | }) | ||
705 | |||
706 | it('Should send a notification when the scheduled update has been proceeded', async function () { | ||
707 | this.timeout(70000) | ||
708 | |||
709 | // In 2 seconds | ||
710 | let updateAt = new Date(new Date().getTime() + 2000) | ||
711 | |||
712 | const data = { | ||
713 | privacy: VideoPrivacy.PRIVATE, | ||
714 | scheduleUpdate: { | ||
715 | updateAt: updateAt.toISOString(), | ||
716 | privacy: VideoPrivacy.PUBLIC | ||
717 | } | ||
718 | } | ||
719 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, data) | ||
720 | |||
721 | await wait(6000) | ||
722 | await checkVideoIsPublished(baseParams, name, uuid, 'presence') | ||
723 | }) | ||
724 | |||
725 | it('Should not send a notification before the video is published', async function () { | ||
726 | this.timeout(20000) | ||
727 | |||
728 | let updateAt = new Date(new Date().getTime() + 100000) | ||
729 | |||
730 | const data = { | ||
731 | privacy: VideoPrivacy.PRIVATE, | ||
732 | scheduleUpdate: { | ||
733 | updateAt: updateAt.toISOString(), | ||
734 | privacy: VideoPrivacy.PUBLIC | ||
735 | } | ||
736 | } | ||
737 | const { name, uuid } = await uploadVideoByRemoteAccount(servers, data) | ||
738 | |||
739 | await wait(6000) | ||
740 | await checkVideoIsPublished(baseParams, name, uuid, 'absence') | ||
741 | }) | ||
742 | }) | ||
743 | |||
744 | describe('My video is imported', function () { | ||
745 | let baseParams: CheckerBaseParams | ||
746 | |||
747 | before(() => { | ||
748 | baseParams = { | ||
749 | server: servers[0], | ||
750 | emails, | ||
751 | socketNotifications: adminNotifications, | ||
752 | token: servers[0].accessToken | ||
753 | } | ||
754 | }) | ||
755 | |||
756 | it('Should send a notification when the video import failed', async function () { | ||
757 | this.timeout(70000) | ||
758 | |||
759 | const name = 'video import ' + uuidv4() | ||
760 | |||
761 | const attributes = { | ||
762 | name, | ||
763 | channelId, | ||
764 | privacy: VideoPrivacy.PRIVATE, | ||
765 | targetUrl: getBadVideoUrl() | ||
766 | } | ||
767 | const res = await importVideo(servers[0].url, servers[0].accessToken, attributes) | ||
768 | const uuid = res.body.video.uuid | ||
769 | |||
770 | await waitJobs(servers) | ||
771 | await checkMyVideoImportIsFinished(baseParams, name, uuid, getBadVideoUrl(), false, 'presence') | ||
772 | }) | ||
773 | |||
774 | it('Should send a notification when the video import succeeded', async function () { | ||
775 | this.timeout(70000) | ||
776 | |||
777 | const name = 'video import ' + uuidv4() | ||
778 | |||
779 | const attributes = { | ||
780 | name, | ||
781 | channelId, | ||
782 | privacy: VideoPrivacy.PRIVATE, | ||
783 | targetUrl: getYoutubeVideoUrl() | ||
784 | } | ||
785 | const res = await importVideo(servers[0].url, servers[0].accessToken, attributes) | ||
786 | const uuid = res.body.video.uuid | ||
787 | |||
788 | await waitJobs(servers) | ||
789 | await checkMyVideoImportIsFinished(baseParams, name, uuid, getYoutubeVideoUrl(), true, 'presence') | ||
790 | }) | ||
791 | }) | ||
792 | |||
793 | describe('New registration', function () { | ||
794 | let baseParams: CheckerBaseParams | ||
795 | |||
796 | before(() => { | ||
797 | baseParams = { | ||
798 | server: servers[0], | ||
799 | emails, | ||
800 | socketNotifications: adminNotifications, | ||
801 | token: servers[0].accessToken | ||
802 | } | ||
803 | }) | ||
804 | |||
805 | it('Should send a notification only to moderators when a user registers on the instance', async function () { | ||
806 | this.timeout(10000) | ||
807 | |||
808 | await registerUser(servers[0].url, 'user_45', 'password') | ||
809 | |||
810 | await waitJobs(servers) | ||
811 | |||
812 | await checkUserRegistered(baseParams, 'user_45', 'presence') | ||
813 | |||
814 | const userOverride = { socketNotifications: userNotifications, token: userAccessToken, check: { web: true, mail: false } } | ||
815 | await checkUserRegistered(immutableAssign(baseParams, userOverride), 'user_45', 'absence') | ||
816 | }) | ||
817 | }) | ||
818 | |||
819 | describe('New actor follow', function () { | ||
820 | let baseParams: CheckerBaseParams | ||
821 | let myChannelName = 'super channel name' | ||
822 | let myUserName = 'super user name' | ||
823 | |||
824 | before(async () => { | ||
825 | baseParams = { | ||
826 | server: servers[0], | ||
827 | emails, | ||
828 | socketNotifications: userNotifications, | ||
829 | token: userAccessToken | ||
830 | } | ||
831 | |||
832 | await updateMyUser({ | ||
833 | url: servers[0].url, | ||
834 | accessToken: servers[0].accessToken, | ||
835 | displayName: 'super root name' | ||
836 | }) | ||
837 | |||
838 | await updateMyUser({ | ||
839 | url: servers[0].url, | ||
840 | accessToken: userAccessToken, | ||
841 | displayName: myUserName | ||
842 | }) | ||
843 | |||
844 | await updateMyUser({ | ||
845 | url: servers[1].url, | ||
846 | accessToken: servers[1].accessToken, | ||
847 | displayName: 'super root 2 name' | ||
848 | }) | ||
849 | |||
850 | await updateVideoChannel(servers[0].url, userAccessToken, 'user_1_channel', { displayName: myChannelName }) | ||
851 | }) | ||
852 | |||
853 | it('Should notify when a local channel is following one of our channel', async function () { | ||
854 | this.timeout(10000) | ||
855 | |||
856 | await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:9001') | ||
857 | await waitJobs(servers) | ||
858 | |||
859 | await checkNewActorFollow(baseParams, 'channel', 'root', 'super root name', myChannelName, 'presence') | ||
860 | |||
861 | await removeUserSubscription(servers[0].url, servers[0].accessToken, 'user_1_channel@localhost:9001') | ||
862 | }) | ||
863 | |||
864 | it('Should notify when a remote channel is following one of our channel', async function () { | ||
865 | this.timeout(10000) | ||
866 | |||
867 | await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:9001') | ||
868 | await waitJobs(servers) | ||
869 | |||
870 | await checkNewActorFollow(baseParams, 'channel', 'root', 'super root 2 name', myChannelName, 'presence') | ||
871 | |||
872 | await removeUserSubscription(servers[1].url, servers[1].accessToken, 'user_1_channel@localhost:9001') | ||
873 | }) | ||
874 | |||
875 | it('Should notify when a local account is following one of our channel', async function () { | ||
876 | this.timeout(10000) | ||
877 | |||
878 | await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1@localhost:9001') | ||
879 | |||
880 | await waitJobs(servers) | ||
881 | |||
882 | await checkNewActorFollow(baseParams, 'account', 'root', 'super root name', myUserName, 'presence') | ||
883 | }) | ||
884 | |||
885 | it('Should notify when a remote account is following one of our channel', async function () { | ||
886 | this.timeout(10000) | ||
887 | |||
888 | await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1@localhost:9001') | ||
889 | |||
890 | await waitJobs(servers) | ||
891 | |||
892 | await checkNewActorFollow(baseParams, 'account', 'root', 'super root 2 name', myUserName, 'presence') | ||
893 | }) | ||
894 | }) | ||
895 | |||
896 | describe('Mark as read', function () { | ||
897 | it('Should mark as read some notifications', async function () { | ||
898 | const res = await getUserNotifications(servers[ 0 ].url, userAccessToken, 2, 3) | ||
899 | const ids = res.body.data.map(n => n.id) | ||
900 | |||
901 | await markAsReadNotifications(servers[ 0 ].url, userAccessToken, ids) | ||
902 | }) | ||
903 | |||
904 | it('Should have the notifications marked as read', async function () { | ||
905 | const res = await getUserNotifications(servers[ 0 ].url, userAccessToken, 0, 10) | ||
906 | |||
907 | const notifications = res.body.data as UserNotification[] | ||
908 | expect(notifications[ 0 ].read).to.be.false | ||
909 | expect(notifications[ 1 ].read).to.be.false | ||
910 | expect(notifications[ 2 ].read).to.be.true | ||
911 | expect(notifications[ 3 ].read).to.be.true | ||
912 | expect(notifications[ 4 ].read).to.be.true | ||
913 | expect(notifications[ 5 ].read).to.be.false | ||
914 | }) | ||
915 | |||
916 | it('Should only list read notifications', async function () { | ||
917 | const res = await getUserNotifications(servers[ 0 ].url, userAccessToken, 0, 10, false) | ||
918 | |||
919 | const notifications = res.body.data as UserNotification[] | ||
920 | for (const notification of notifications) { | ||
921 | expect(notification.read).to.be.true | ||
922 | } | ||
923 | }) | ||
924 | |||
925 | it('Should only list unread notifications', async function () { | ||
926 | const res = await getUserNotifications(servers[ 0 ].url, userAccessToken, 0, 10, true) | ||
927 | |||
928 | const notifications = res.body.data as UserNotification[] | ||
929 | for (const notification of notifications) { | ||
930 | expect(notification.read).to.be.false | ||
931 | } | ||
932 | }) | ||
933 | |||
934 | it('Should mark as read all notifications', async function () { | ||
935 | await markAsReadAllNotifications(servers[ 0 ].url, userAccessToken) | ||
936 | |||
937 | const res = await getUserNotifications(servers[ 0 ].url, userAccessToken, 0, 10, true) | ||
938 | |||
939 | expect(res.body.total).to.equal(0) | ||
940 | expect(res.body.data).to.have.lengthOf(0) | ||
941 | }) | ||
942 | }) | ||
943 | |||
944 | describe('Notification settings', function () { | ||
945 | let baseParams: CheckerBaseParams | ||
946 | |||
947 | before(() => { | ||
948 | baseParams = { | ||
949 | server: servers[0], | ||
950 | emails, | ||
951 | socketNotifications: userNotifications, | ||
952 | token: userAccessToken | ||
953 | } | ||
954 | }) | ||
955 | |||
956 | it('Should not have notifications', async function () { | ||
957 | this.timeout(10000) | ||
958 | |||
959 | await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(allNotificationSettings, { | ||
960 | newVideoFromSubscription: UserNotificationSettingValue.NONE | ||
961 | })) | ||
962 | |||
963 | { | ||
964 | const res = await getMyUserInformation(servers[0].url, userAccessToken) | ||
965 | const info = res.body as User | ||
966 | expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE) | ||
967 | } | ||
968 | |||
969 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
970 | |||
971 | const check = { web: true, mail: true } | ||
972 | await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence') | ||
973 | }) | ||
974 | |||
975 | it('Should only have web notifications', async function () { | ||
976 | this.timeout(10000) | ||
977 | |||
978 | await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(allNotificationSettings, { | ||
979 | newVideoFromSubscription: UserNotificationSettingValue.WEB | ||
980 | })) | ||
981 | |||
982 | { | ||
983 | const res = await getMyUserInformation(servers[0].url, userAccessToken) | ||
984 | const info = res.body as User | ||
985 | expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB) | ||
986 | } | ||
987 | |||
988 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
989 | |||
990 | { | ||
991 | const check = { mail: true, web: false } | ||
992 | await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence') | ||
993 | } | ||
994 | |||
995 | { | ||
996 | const check = { mail: false, web: true } | ||
997 | await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'presence') | ||
998 | } | ||
999 | }) | ||
1000 | |||
1001 | it('Should only have mail notifications', async function () { | ||
1002 | this.timeout(10000) | ||
1003 | |||
1004 | await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(allNotificationSettings, { | ||
1005 | newVideoFromSubscription: UserNotificationSettingValue.EMAIL | ||
1006 | })) | ||
1007 | |||
1008 | { | ||
1009 | const res = await getMyUserInformation(servers[0].url, userAccessToken) | ||
1010 | const info = res.body as User | ||
1011 | expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL) | ||
1012 | } | ||
1013 | |||
1014 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
1015 | |||
1016 | { | ||
1017 | const check = { mail: false, web: true } | ||
1018 | await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'absence') | ||
1019 | } | ||
1020 | |||
1021 | { | ||
1022 | const check = { mail: true, web: false } | ||
1023 | await checkNewVideoFromSubscription(immutableAssign(baseParams, { check }), name, uuid, 'presence') | ||
1024 | } | ||
1025 | }) | ||
1026 | |||
1027 | it('Should have email and web notifications', async function () { | ||
1028 | this.timeout(10000) | ||
1029 | |||
1030 | await updateMyNotificationSettings(servers[0].url, userAccessToken, immutableAssign(allNotificationSettings, { | ||
1031 | newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL | ||
1032 | })) | ||
1033 | |||
1034 | { | ||
1035 | const res = await getMyUserInformation(servers[0].url, userAccessToken) | ||
1036 | const info = res.body as User | ||
1037 | expect(info.notificationSettings.newVideoFromSubscription).to.equal( | ||
1038 | UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL | ||
1039 | ) | ||
1040 | } | ||
1041 | |||
1042 | const { name, uuid } = await uploadVideoByLocalAccount(servers) | ||
1043 | |||
1044 | await checkNewVideoFromSubscription(baseParams, name, uuid, 'presence') | ||
1045 | }) | ||
1046 | }) | ||
1047 | |||
1048 | after(async function () { | ||
1049 | MockSmtpServer.Instance.kill() | ||
1050 | |||
1051 | killallServers(servers) | ||
1052 | }) | ||
1053 | }) | ||
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts index 65b80540c..88a7187d6 100644 --- a/server/tests/api/users/user-subscriptions.ts +++ b/server/tests/api/users/user-subscriptions.ts | |||
@@ -2,18 +2,27 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { createUser, doubleFollow, flushAndRunMultipleServers, follow, getVideosList, unfollow, updateVideo, userLogin } from '../../utils' | 5 | import { |
6 | import { killallServers, ServerInfo, uploadVideo } from '../../utils/index' | 6 | createUser, |
7 | import { setAccessTokensToServers } from '../../utils/users/login' | 7 | doubleFollow, |
8 | flushAndRunMultipleServers, | ||
9 | follow, | ||
10 | getVideosList, | ||
11 | unfollow, | ||
12 | updateVideo, | ||
13 | userLogin | ||
14 | } from '../../../../shared/utils' | ||
15 | import { killallServers, ServerInfo, uploadVideo } from '../../../../shared/utils/index' | ||
16 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' | ||
8 | import { Video, VideoChannel } from '../../../../shared/models/videos' | 17 | import { Video, VideoChannel } from '../../../../shared/models/videos' |
9 | import { waitJobs } from '../../utils/server/jobs' | 18 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
10 | import { | 19 | import { |
11 | addUserSubscription, | 20 | addUserSubscription, |
12 | listUserSubscriptions, | 21 | listUserSubscriptions, |
13 | listUserSubscriptionVideos, | 22 | listUserSubscriptionVideos, |
14 | removeUserSubscription, | 23 | removeUserSubscription, |
15 | getUserSubscription, areSubscriptionsExist | 24 | getUserSubscription, areSubscriptionsExist |
16 | } from '../../utils/users/user-subscriptions' | 25 | } from '../../../../shared/utils/users/user-subscriptions' |
17 | 26 | ||
18 | const expect = chai.expect | 27 | const expect = chai.expect |
19 | 28 | ||
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts index d8699db17..006d6cdf0 100644 --- a/server/tests/api/users/users-multiple-servers.ts +++ b/server/tests/api/users/users-multiple-servers.ts | |||
@@ -13,13 +13,13 @@ import { | |||
13 | removeUser, | 13 | removeUser, |
14 | updateMyUser, | 14 | updateMyUser, |
15 | userLogin | 15 | userLogin |
16 | } from '../../utils' | 16 | } from '../../../../shared/utils' |
17 | import { getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index' | 17 | import { getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../../../shared/utils/index' |
18 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts' | 18 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../../../shared/utils/users/accounts' |
19 | import { setAccessTokensToServers } from '../../utils/users/login' | 19 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' |
20 | import { User } from '../../../../shared/models/users' | 20 | import { User } from '../../../../shared/models/users' |
21 | import { VideoChannel } from '../../../../shared/models/videos' | 21 | import { VideoChannel } from '../../../../shared/models/videos' |
22 | import { waitJobs } from '../../utils/server/jobs' | 22 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
23 | 23 | ||
24 | const expect = chai.expect | 24 | const expect = chai.expect |
25 | 25 | ||
diff --git a/server/tests/api/users/users-verification.ts b/server/tests/api/users/users-verification.ts index fa5f5e371..babeda2b8 100644 --- a/server/tests/api/users/users-verification.ts +++ b/server/tests/api/users/users-verification.ts | |||
@@ -4,11 +4,11 @@ import * as chai from 'chai' | |||
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { | 5 | import { |
6 | registerUser, flushTests, getUserInformation, getMyUserInformation, killallServers, | 6 | registerUser, flushTests, getUserInformation, getMyUserInformation, killallServers, |
7 | userLogin, login, runServer, ServerInfo, verifyEmail, updateCustomSubConfig | 7 | userLogin, login, runServer, ServerInfo, verifyEmail, updateCustomSubConfig, wait |
8 | } from '../../utils' | 8 | } from '../../../../shared/utils' |
9 | import { setAccessTokensToServers } from '../../utils/users/login' | 9 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' |
10 | import { mockSmtpServer } from '../../utils/miscs/email' | 10 | import { MockSmtpServer } from '../../../../shared/utils/miscs/email' |
11 | import { waitJobs } from '../../utils/server/jobs' | 11 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
12 | 12 | ||
13 | const expect = chai.expect | 13 | const expect = chai.expect |
14 | 14 | ||
@@ -30,7 +30,7 @@ describe('Test users account verification', function () { | |||
30 | before(async function () { | 30 | before(async function () { |
31 | this.timeout(30000) | 31 | this.timeout(30000) |
32 | 32 | ||
33 | await mockSmtpServer(emails) | 33 | await MockSmtpServer.Instance.collectEmails(emails) |
34 | 34 | ||
35 | await flushTests() | 35 | await flushTests() |
36 | 36 | ||
@@ -123,6 +123,7 @@ describe('Test users account verification', function () { | |||
123 | }) | 123 | }) |
124 | 124 | ||
125 | after(async function () { | 125 | after(async function () { |
126 | MockSmtpServer.Instance.kill() | ||
126 | killallServers([ server ]) | 127 | killallServers([ server ]) |
127 | 128 | ||
128 | // Keep the logs if the test failed | 129 | // Keep the logs if the test failed |
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 8b9c6b455..c4465d541 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -32,10 +32,10 @@ import { | |||
32 | updateUser, | 32 | updateUser, |
33 | uploadVideo, | 33 | uploadVideo, |
34 | userLogin | 34 | userLogin |
35 | } from '../../utils/index' | 35 | } from '../../../../shared/utils/index' |
36 | import { follow } from '../../utils/server/follows' | 36 | import { follow } from '../../../../shared/utils/server/follows' |
37 | import { setAccessTokensToServers } from '../../utils/users/login' | 37 | import { setAccessTokensToServers } from '../../../../shared/utils/users/login' |
38 | import { getMyVideos } from '../../utils/videos/videos' | 38 | import { getMyVideos } from '../../../../shared/utils/videos/videos' |
39 | 39 | ||
40 | const expect = chai.expect | 40 | const expect = chai.expect |
41 | 41 | ||
@@ -180,7 +180,7 @@ describe('Test users', function () { | |||
180 | it('Should be able to upload a video again') | 180 | it('Should be able to upload a video again') |
181 | 181 | ||
182 | it('Should be able to create a new user', async function () { | 182 | it('Should be able to create a new user', async function () { |
183 | await createUser(server.url, accessToken, user.username,user.password, 2 * 1024 * 1024) | 183 | await createUser(server.url, accessToken, user.username, user.password, 2 * 1024 * 1024) |
184 | }) | 184 | }) |
185 | 185 | ||
186 | it('Should be able to login with this user', async function () { | 186 | it('Should be able to login with this user', async function () { |
@@ -322,6 +322,40 @@ describe('Test users', function () { | |||
322 | expect(users[ 1 ].nsfwPolicy).to.equal('display') | 322 | expect(users[ 1 ].nsfwPolicy).to.equal('display') |
323 | }) | 323 | }) |
324 | 324 | ||
325 | it('Should search user by username', async function () { | ||
326 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'oot') | ||
327 | const users = res.body.data as User[] | ||
328 | |||
329 | expect(res.body.total).to.equal(1) | ||
330 | expect(users.length).to.equal(1) | ||
331 | |||
332 | expect(users[ 0 ].username).to.equal('root') | ||
333 | }) | ||
334 | |||
335 | it('Should search user by email', async function () { | ||
336 | { | ||
337 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'r_1@exam') | ||
338 | const users = res.body.data as User[] | ||
339 | |||
340 | expect(res.body.total).to.equal(1) | ||
341 | expect(users.length).to.equal(1) | ||
342 | |||
343 | expect(users[ 0 ].username).to.equal('user_1') | ||
344 | expect(users[ 0 ].email).to.equal('user_1@example.com') | ||
345 | } | ||
346 | |||
347 | { | ||
348 | const res = await getUsersListPaginationAndSort(server.url, server.accessToken, 0, 2, 'createdAt', 'example') | ||
349 | const users = res.body.data as User[] | ||
350 | |||
351 | expect(res.body.total).to.equal(2) | ||
352 | expect(users.length).to.equal(2) | ||
353 | |||
354 | expect(users[ 0 ].username).to.equal('root') | ||
355 | expect(users[ 1 ].username).to.equal('user_1') | ||
356 | } | ||
357 | }) | ||
358 | |||
325 | it('Should update my password', async function () { | 359 | it('Should update my password', async function () { |
326 | await updateMyUser({ | 360 | await updateMyUser({ |
327 | url: server.url, | 361 | url: server.url, |
@@ -444,6 +478,7 @@ describe('Test users', function () { | |||
444 | userId, | 478 | userId, |
445 | accessToken, | 479 | accessToken, |
446 | email: 'updated2@example.com', | 480 | email: 'updated2@example.com', |
481 | emailVerified: true, | ||
447 | videoQuota: 42, | 482 | videoQuota: 42, |
448 | role: UserRole.MODERATOR | 483 | role: UserRole.MODERATOR |
449 | }) | 484 | }) |
@@ -453,6 +488,7 @@ describe('Test users', function () { | |||
453 | 488 | ||
454 | expect(user.username).to.equal('user_1') | 489 | expect(user.username).to.equal('user_1') |
455 | expect(user.email).to.equal('updated2@example.com') | 490 | expect(user.email).to.equal('updated2@example.com') |
491 | expect(user.emailVerified).to.be.true | ||
456 | expect(user.nsfwPolicy).to.equal('do_not_list') | 492 | expect(user.nsfwPolicy).to.equal('do_not_list') |
457 | expect(user.videoQuota).to.equal(42) | 493 | expect(user.videoQuota).to.equal(42) |
458 | expect(user.roleLabel).to.equal('Moderator') | 494 | expect(user.roleLabel).to.equal('Moderator') |
@@ -465,8 +501,20 @@ describe('Test users', function () { | |||
465 | accessTokenUser = await userLogin(server, user) | 501 | accessTokenUser = await userLogin(server, user) |
466 | }) | 502 | }) |
467 | 503 | ||
468 | it('Should not be able to delete a user by a moderator', async function () { | 504 | it('Should be able to update another user password', async function () { |
469 | await removeUser(server.url, 2, accessTokenUser, 403) | 505 | await updateUser({ |
506 | url: server.url, | ||
507 | userId, | ||
508 | accessToken, | ||
509 | password: 'password updated' | ||
510 | }) | ||
511 | |||
512 | await getMyUserVideoQuotaUsed(server.url, accessTokenUser, 401) | ||
513 | |||
514 | await userLogin(server, user, 400) | ||
515 | |||
516 | user.password = 'password updated' | ||
517 | accessTokenUser = await userLogin(server, user) | ||
470 | }) | 518 | }) |
471 | 519 | ||
472 | it('Should be able to list video blacklist by a moderator', async function () { | 520 | it('Should be able to list video blacklist by a moderator', async function () { |
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts index 09bb62a8d..a501a80b2 100644 --- a/server/tests/api/videos/index.ts +++ b/server/tests/api/videos/index.ts | |||
@@ -3,16 +3,17 @@ import './services' | |||
3 | import './single-server' | 3 | import './single-server' |
4 | import './video-abuse' | 4 | import './video-abuse' |
5 | import './video-blacklist' | 5 | import './video-blacklist' |
6 | import './video-blacklist-management' | ||
7 | import './video-captions' | 6 | import './video-captions' |
8 | import './video-change-ownership' | 7 | import './video-change-ownership' |
9 | import './video-channels' | 8 | import './video-channels' |
10 | import './video-comments' | 9 | import './video-comments' |
11 | import './video-description' | 10 | import './video-description' |
11 | import './video-hls' | ||
12 | import './video-imports' | 12 | import './video-imports' |
13 | import './video-nsfw' | 13 | import './video-nsfw' |
14 | import './video-privacy' | 14 | import './video-privacy' |
15 | import './video-schedule-update' | 15 | import './video-schedule-update' |
16 | import './video-transcoder' | 16 | import './video-transcoder' |
17 | import './videos-filter' | ||
17 | import './videos-history' | 18 | import './videos-history' |
18 | import './videos-overview' | 19 | import './videos-overview' |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index 99b74ccff..1b471ba79 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -8,6 +8,7 @@ import { VideoPrivacy } from '../../../../shared/models/videos' | |||
8 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | 8 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' |
9 | import { | 9 | import { |
10 | addVideoChannel, | 10 | addVideoChannel, |
11 | checkTmpIsEmpty, | ||
11 | checkVideoFilesWereRemoved, | 12 | checkVideoFilesWereRemoved, |
12 | completeVideoCheck, | 13 | completeVideoCheck, |
13 | createUser, | 14 | createUser, |
@@ -31,15 +32,15 @@ import { | |||
31 | viewVideo, | 32 | viewVideo, |
32 | wait, | 33 | wait, |
33 | webtorrentAdd | 34 | webtorrentAdd |
34 | } from '../../utils' | 35 | } from '../../../../shared/utils' |
35 | import { | 36 | import { |
36 | addVideoCommentReply, | 37 | addVideoCommentReply, |
37 | addVideoCommentThread, | 38 | addVideoCommentThread, |
38 | deleteVideoComment, | 39 | deleteVideoComment, |
39 | getVideoCommentThreads, | 40 | getVideoCommentThreads, |
40 | getVideoThreadComments | 41 | getVideoThreadComments |
41 | } from '../../utils/videos/video-comments' | 42 | } from '../../../../shared/utils/videos/video-comments' |
42 | import { waitJobs } from '../../utils/server/jobs' | 43 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
43 | 44 | ||
44 | const expect = chai.expect | 45 | const expect = chai.expect |
45 | 46 | ||
@@ -995,19 +996,19 @@ describe('Test multiple servers', function () { | |||
995 | files: [ | 996 | files: [ |
996 | { | 997 | { |
997 | resolution: 720, | 998 | resolution: 720, |
998 | size: 36000 | 999 | size: 72000 |
999 | }, | 1000 | }, |
1000 | { | 1001 | { |
1001 | resolution: 480, | 1002 | resolution: 480, |
1002 | size: 21000 | 1003 | size: 45000 |
1003 | }, | 1004 | }, |
1004 | { | 1005 | { |
1005 | resolution: 360, | 1006 | resolution: 360, |
1006 | size: 17000 | 1007 | size: 34600 |
1007 | }, | 1008 | }, |
1008 | { | 1009 | { |
1009 | resolution: 240, | 1010 | resolution: 240, |
1010 | size: 13000 | 1011 | size: 24770 |
1011 | } | 1012 | } |
1012 | ] | 1013 | ] |
1013 | } | 1014 | } |
@@ -1016,6 +1017,14 @@ describe('Test multiple servers', function () { | |||
1016 | }) | 1017 | }) |
1017 | }) | 1018 | }) |
1018 | 1019 | ||
1020 | describe('TMP directory', function () { | ||
1021 | it('Should have an empty tmp directory', async function () { | ||
1022 | for (const server of servers) { | ||
1023 | await checkTmpIsEmpty(server) | ||
1024 | } | ||
1025 | }) | ||
1026 | }) | ||
1027 | |||
1019 | after(async function () { | 1028 | after(async function () { |
1020 | killallServers(servers) | 1029 | killallServers(servers) |
1021 | 1030 | ||
diff --git a/server/tests/api/videos/services.ts b/server/tests/api/videos/services.ts index 2f1424292..2da86964f 100644 --- a/server/tests/api/videos/services.ts +++ b/server/tests/api/videos/services.ts | |||
@@ -2,8 +2,16 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { flushTests, getOEmbed, getVideosList, killallServers, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../utils/index' | 5 | import { |
6 | import { runServer } from '../../utils/server/servers' | 6 | flushTests, |
7 | getOEmbed, | ||
8 | getVideosList, | ||
9 | killallServers, | ||
10 | ServerInfo, | ||
11 | setAccessTokensToServers, | ||
12 | uploadVideo | ||
13 | } from '../../../../shared/utils/index' | ||
14 | import { runServer } from '../../../../shared/utils/server/servers' | ||
7 | 15 | ||
8 | const expect = chai.expect | 16 | const expect = chai.expect |
9 | 17 | ||
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 92d42eb80..cfdcbaf3f 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -28,7 +28,7 @@ import { | |||
28 | uploadVideo, | 28 | uploadVideo, |
29 | viewVideo, | 29 | viewVideo, |
30 | wait | 30 | wait |
31 | } from '../../utils' | 31 | } from '../../../../shared/utils' |
32 | 32 | ||
33 | const expect = chai.expect | 33 | const expect = chai.expect |
34 | 34 | ||
@@ -120,7 +120,7 @@ describe('Test a single server', function () { | |||
120 | const categories = res.body | 120 | const categories = res.body |
121 | expect(Object.keys(categories)).to.have.length.above(10) | 121 | expect(Object.keys(categories)).to.have.length.above(10) |
122 | 122 | ||
123 | expect(categories[11]).to.equal('News') | 123 | expect(categories[11]).to.equal('News & Politics') |
124 | }) | 124 | }) |
125 | 125 | ||
126 | it('Should list video licences', async function () { | 126 | it('Should list video licences', async function () { |
diff --git a/server/tests/api/videos/video-abuse.ts b/server/tests/api/videos/video-abuse.ts index a17f3c8de..3a7b623da 100644 --- a/server/tests/api/videos/video-abuse.ts +++ b/server/tests/api/videos/video-abuse.ts | |||
@@ -14,9 +14,9 @@ import { | |||
14 | setAccessTokensToServers, | 14 | setAccessTokensToServers, |
15 | updateVideoAbuse, | 15 | updateVideoAbuse, |
16 | uploadVideo | 16 | uploadVideo |
17 | } from '../../utils/index' | 17 | } from '../../../../shared/utils/index' |
18 | import { doubleFollow } from '../../utils/server/follows' | 18 | import { doubleFollow } from '../../../../shared/utils/server/follows' |
19 | import { waitJobs } from '../../utils/server/jobs' | 19 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
20 | 20 | ||
21 | const expect = chai.expect | 21 | const expect = chai.expect |
22 | 22 | ||
diff --git a/server/tests/api/videos/video-blacklist-management.ts b/server/tests/api/videos/video-blacklist-management.ts deleted file mode 100644 index 7bf39dc99..000000000 --- a/server/tests/api/videos/video-blacklist-management.ts +++ /dev/null | |||
@@ -1,193 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import * as lodash from 'lodash' | ||
5 | import 'mocha' | ||
6 | import { | ||
7 | addVideoToBlacklist, | ||
8 | flushAndRunMultipleServers, | ||
9 | getBlacklistedVideosList, | ||
10 | getMyVideos, | ||
11 | getSortedBlacklistedVideosList, | ||
12 | getVideosList, | ||
13 | killallServers, | ||
14 | removeVideoFromBlacklist, | ||
15 | ServerInfo, | ||
16 | setAccessTokensToServers, | ||
17 | updateVideoBlacklist, | ||
18 | uploadVideo | ||
19 | } from '../../utils/index' | ||
20 | import { doubleFollow } from '../../utils/server/follows' | ||
21 | import { waitJobs } from '../../utils/server/jobs' | ||
22 | import { VideoAbuse } from '../../../../shared/models/videos' | ||
23 | |||
24 | const expect = chai.expect | ||
25 | const orderBy = lodash.orderBy | ||
26 | |||
27 | describe('Test video blacklist management', function () { | ||
28 | let servers: ServerInfo[] = [] | ||
29 | let videoId: number | ||
30 | |||
31 | async function blacklistVideosOnServer (server: ServerInfo) { | ||
32 | const res = await getVideosList(server.url) | ||
33 | |||
34 | const videos = res.body.data | ||
35 | for (let video of videos) { | ||
36 | await addVideoToBlacklist(server.url, server.accessToken, video.id, 'super reason') | ||
37 | } | ||
38 | } | ||
39 | |||
40 | before(async function () { | ||
41 | this.timeout(50000) | ||
42 | |||
43 | // Run servers | ||
44 | servers = await flushAndRunMultipleServers(2) | ||
45 | |||
46 | // Get the access tokens | ||
47 | await setAccessTokensToServers(servers) | ||
48 | |||
49 | // Server 1 and server 2 follow each other | ||
50 | await doubleFollow(servers[0], servers[1]) | ||
51 | |||
52 | // Upload 2 videos on server 2 | ||
53 | await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on server 2' }) | ||
54 | await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on server 2' }) | ||
55 | |||
56 | // Wait videos propagation, server 2 has transcoding enabled | ||
57 | await waitJobs(servers) | ||
58 | |||
59 | // Blacklist the two videos on server 1 | ||
60 | await blacklistVideosOnServer(servers[0]) | ||
61 | }) | ||
62 | |||
63 | describe('When listing blacklisted videos', function () { | ||
64 | it('Should display all the blacklisted videos', async function () { | ||
65 | const res = await getBlacklistedVideosList(servers[0].url, servers[0].accessToken) | ||
66 | |||
67 | expect(res.body.total).to.equal(2) | ||
68 | |||
69 | const blacklistedVideos = res.body.data | ||
70 | expect(blacklistedVideos).to.be.an('array') | ||
71 | expect(blacklistedVideos.length).to.equal(2) | ||
72 | |||
73 | for (const blacklistedVideo of blacklistedVideos) { | ||
74 | expect(blacklistedVideo.reason).to.equal('super reason') | ||
75 | videoId = blacklistedVideo.video.id | ||
76 | } | ||
77 | }) | ||
78 | |||
79 | it('Should get the correct sort when sorting by descending id', async function () { | ||
80 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-id') | ||
81 | expect(res.body.total).to.equal(2) | ||
82 | |||
83 | const blacklistedVideos = res.body.data | ||
84 | expect(blacklistedVideos).to.be.an('array') | ||
85 | expect(blacklistedVideos.length).to.equal(2) | ||
86 | |||
87 | const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ]) | ||
88 | |||
89 | expect(blacklistedVideos).to.deep.equal(result) | ||
90 | }) | ||
91 | |||
92 | it('Should get the correct sort when sorting by descending video name', async function () { | ||
93 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
94 | expect(res.body.total).to.equal(2) | ||
95 | |||
96 | const blacklistedVideos = res.body.data | ||
97 | expect(blacklistedVideos).to.be.an('array') | ||
98 | expect(blacklistedVideos.length).to.equal(2) | ||
99 | |||
100 | const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ]) | ||
101 | |||
102 | expect(blacklistedVideos).to.deep.equal(result) | ||
103 | }) | ||
104 | |||
105 | it('Should get the correct sort when sorting by ascending creation date', async function () { | ||
106 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt') | ||
107 | expect(res.body.total).to.equal(2) | ||
108 | |||
109 | const blacklistedVideos = res.body.data | ||
110 | expect(blacklistedVideos).to.be.an('array') | ||
111 | expect(blacklistedVideos.length).to.equal(2) | ||
112 | |||
113 | const result = orderBy(res.body.data, [ 'createdAt' ]) | ||
114 | |||
115 | expect(blacklistedVideos).to.deep.equal(result) | ||
116 | }) | ||
117 | }) | ||
118 | |||
119 | describe('When updating blacklisted videos', function () { | ||
120 | it('Should change the reason', async function () { | ||
121 | await updateVideoBlacklist(servers[0].url, servers[0].accessToken, videoId, 'my super reason updated') | ||
122 | |||
123 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
124 | const video = res.body.data.find(b => b.video.id === videoId) | ||
125 | |||
126 | expect(video.reason).to.equal('my super reason updated') | ||
127 | }) | ||
128 | }) | ||
129 | |||
130 | describe('When listing my videos', function () { | ||
131 | it('Should display blacklisted videos', async function () { | ||
132 | await blacklistVideosOnServer(servers[1]) | ||
133 | |||
134 | const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 5) | ||
135 | |||
136 | expect(res.body.total).to.equal(2) | ||
137 | expect(res.body.data).to.have.lengthOf(2) | ||
138 | |||
139 | for (const video of res.body.data) { | ||
140 | expect(video.blacklisted).to.be.true | ||
141 | expect(video.blacklistedReason).to.equal('super reason') | ||
142 | } | ||
143 | }) | ||
144 | }) | ||
145 | |||
146 | describe('When removing a blacklisted video', function () { | ||
147 | let videoToRemove: VideoAbuse | ||
148 | let blacklist = [] | ||
149 | |||
150 | it('Should not have any video in videos list on server 1', async function () { | ||
151 | const res = await getVideosList(servers[0].url) | ||
152 | expect(res.body.total).to.equal(0) | ||
153 | expect(res.body.data).to.be.an('array') | ||
154 | expect(res.body.data.length).to.equal(0) | ||
155 | }) | ||
156 | |||
157 | it('Should remove a video from the blacklist on server 1', async function () { | ||
158 | // Get one video in the blacklist | ||
159 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
160 | videoToRemove = res.body.data[0] | ||
161 | blacklist = res.body.data.slice(1) | ||
162 | |||
163 | // Remove it | ||
164 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoToRemove.video.id) | ||
165 | }) | ||
166 | |||
167 | it('Should have the ex-blacklisted video in videos list on server 1', async function () { | ||
168 | const res = await getVideosList(servers[0].url) | ||
169 | expect(res.body.total).to.equal(1) | ||
170 | |||
171 | const videos = res.body.data | ||
172 | expect(videos).to.be.an('array') | ||
173 | expect(videos.length).to.equal(1) | ||
174 | |||
175 | expect(videos[0].name).to.equal(videoToRemove.video.name) | ||
176 | expect(videos[0].id).to.equal(videoToRemove.video.id) | ||
177 | }) | ||
178 | |||
179 | it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () { | ||
180 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
181 | expect(res.body.total).to.equal(1) | ||
182 | |||
183 | const videos = res.body.data | ||
184 | expect(videos).to.be.an('array') | ||
185 | expect(videos.length).to.equal(1) | ||
186 | expect(videos).to.deep.equal(blacklist) | ||
187 | }) | ||
188 | }) | ||
189 | |||
190 | after(async function () { | ||
191 | killallServers(servers) | ||
192 | }) | ||
193 | }) | ||
diff --git a/server/tests/api/videos/video-blacklist.ts b/server/tests/api/videos/video-blacklist.ts index de4c68f1d..d39ad63b4 100644 --- a/server/tests/api/videos/video-blacklist.ts +++ b/server/tests/api/videos/video-blacklist.ts | |||
@@ -1,24 +1,43 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | 1 | /* tslint:disable:no-unused-expression */ |
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import { orderBy } from 'lodash' | ||
4 | import 'mocha' | 5 | import 'mocha' |
5 | import { | 6 | import { |
6 | addVideoToBlacklist, | 7 | addVideoToBlacklist, |
7 | flushAndRunMultipleServers, | 8 | flushAndRunMultipleServers, |
9 | getBlacklistedVideosList, | ||
10 | getMyVideos, | ||
11 | getSortedBlacklistedVideosList, | ||
8 | getVideosList, | 12 | getVideosList, |
9 | killallServers, | 13 | killallServers, |
14 | removeVideoFromBlacklist, | ||
10 | searchVideo, | 15 | searchVideo, |
11 | ServerInfo, | 16 | ServerInfo, |
12 | setAccessTokensToServers, | 17 | setAccessTokensToServers, |
13 | uploadVideo | 18 | updateVideo, |
14 | } from '../../utils/index' | 19 | updateVideoBlacklist, |
15 | import { doubleFollow } from '../../utils/server/follows' | 20 | uploadVideo, |
16 | import { waitJobs } from '../../utils/server/jobs' | 21 | viewVideo |
22 | } from '../../../../shared/utils/index' | ||
23 | import { doubleFollow } from '../../../../shared/utils/server/follows' | ||
24 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
25 | import { VideoBlacklist } from '../../../../shared/models/videos' | ||
17 | 26 | ||
18 | const expect = chai.expect | 27 | const expect = chai.expect |
19 | 28 | ||
20 | describe('Test video blacklists', function () { | 29 | describe('Test video blacklist management', function () { |
21 | let servers: ServerInfo[] = [] | 30 | let servers: ServerInfo[] = [] |
31 | let videoId: number | ||
32 | |||
33 | async function blacklistVideosOnServer (server: ServerInfo) { | ||
34 | const res = await getVideosList(server.url) | ||
35 | |||
36 | const videos = res.body.data | ||
37 | for (let video of videos) { | ||
38 | await addVideoToBlacklist(server.url, server.accessToken, video.id, 'super reason') | ||
39 | } | ||
40 | } | ||
22 | 41 | ||
23 | before(async function () { | 42 | before(async function () { |
24 | this.timeout(50000) | 43 | this.timeout(50000) |
@@ -32,58 +51,270 @@ describe('Test video blacklists', function () { | |||
32 | // Server 1 and server 2 follow each other | 51 | // Server 1 and server 2 follow each other |
33 | await doubleFollow(servers[0], servers[1]) | 52 | await doubleFollow(servers[0], servers[1]) |
34 | 53 | ||
35 | // Upload a video on server 2 | 54 | // Upload 2 videos on server 2 |
36 | const videoAttributes = { | 55 | await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 1st video', description: 'A video on server 2' }) |
37 | name: 'my super name for server 2', | 56 | await uploadVideo(servers[1].url, servers[1].accessToken, { name: 'My 2nd video', description: 'A video on server 2' }) |
38 | description: 'my super description for server 2' | ||
39 | } | ||
40 | await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) | ||
41 | 57 | ||
42 | // Wait videos propagation, server 2 has transcoding enabled | 58 | // Wait videos propagation, server 2 has transcoding enabled |
43 | await waitJobs(servers) | 59 | await waitJobs(servers) |
44 | 60 | ||
45 | const res = await getVideosList(servers[0].url) | 61 | // Blacklist the two videos on server 1 |
46 | const videos = res.body.data | 62 | await blacklistVideosOnServer(servers[0]) |
63 | }) | ||
64 | |||
65 | describe('When listing/searching videos', function () { | ||
47 | 66 | ||
48 | expect(videos.length).to.equal(1) | 67 | it('Should not have the video blacklisted in videos list/search on server 1', async function () { |
68 | { | ||
69 | const res = await getVideosList(servers[ 0 ].url) | ||
49 | 70 | ||
50 | servers[0].remoteVideo = videos.find(video => video.name === 'my super name for server 2') | 71 | expect(res.body.total).to.equal(0) |
72 | expect(res.body.data).to.be.an('array') | ||
73 | expect(res.body.data.length).to.equal(0) | ||
74 | } | ||
75 | |||
76 | { | ||
77 | const res = await searchVideo(servers[ 0 ].url, 'name') | ||
78 | |||
79 | expect(res.body.total).to.equal(0) | ||
80 | expect(res.body.data).to.be.an('array') | ||
81 | expect(res.body.data.length).to.equal(0) | ||
82 | } | ||
83 | }) | ||
84 | |||
85 | it('Should have the blacklisted video in videos list/search on server 2', async function () { | ||
86 | { | ||
87 | const res = await getVideosList(servers[ 1 ].url) | ||
88 | |||
89 | expect(res.body.total).to.equal(2) | ||
90 | expect(res.body.data).to.be.an('array') | ||
91 | expect(res.body.data.length).to.equal(2) | ||
92 | } | ||
93 | |||
94 | { | ||
95 | const res = await searchVideo(servers[ 1 ].url, 'video') | ||
96 | |||
97 | expect(res.body.total).to.equal(2) | ||
98 | expect(res.body.data).to.be.an('array') | ||
99 | expect(res.body.data.length).to.equal(2) | ||
100 | } | ||
101 | }) | ||
51 | }) | 102 | }) |
52 | 103 | ||
53 | it('Should blacklist a remote video on server 1', async function () { | 104 | describe('When listing blacklisted videos', function () { |
54 | await addVideoToBlacklist(servers[0].url, servers[0].accessToken, servers[0].remoteVideo.id) | 105 | it('Should display all the blacklisted videos', async function () { |
106 | const res = await getBlacklistedVideosList(servers[0].url, servers[0].accessToken) | ||
107 | |||
108 | expect(res.body.total).to.equal(2) | ||
109 | |||
110 | const blacklistedVideos = res.body.data | ||
111 | expect(blacklistedVideos).to.be.an('array') | ||
112 | expect(blacklistedVideos.length).to.equal(2) | ||
113 | |||
114 | for (const blacklistedVideo of blacklistedVideos) { | ||
115 | expect(blacklistedVideo.reason).to.equal('super reason') | ||
116 | videoId = blacklistedVideo.video.id | ||
117 | } | ||
118 | }) | ||
119 | |||
120 | it('Should get the correct sort when sorting by descending id', async function () { | ||
121 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-id') | ||
122 | expect(res.body.total).to.equal(2) | ||
123 | |||
124 | const blacklistedVideos = res.body.data | ||
125 | expect(blacklistedVideos).to.be.an('array') | ||
126 | expect(blacklistedVideos.length).to.equal(2) | ||
127 | |||
128 | const result = orderBy(res.body.data, [ 'id' ], [ 'desc' ]) | ||
129 | |||
130 | expect(blacklistedVideos).to.deep.equal(result) | ||
131 | }) | ||
132 | |||
133 | it('Should get the correct sort when sorting by descending video name', async function () { | ||
134 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
135 | expect(res.body.total).to.equal(2) | ||
136 | |||
137 | const blacklistedVideos = res.body.data | ||
138 | expect(blacklistedVideos).to.be.an('array') | ||
139 | expect(blacklistedVideos.length).to.equal(2) | ||
140 | |||
141 | const result = orderBy(res.body.data, [ 'name' ], [ 'desc' ]) | ||
142 | |||
143 | expect(blacklistedVideos).to.deep.equal(result) | ||
144 | }) | ||
145 | |||
146 | it('Should get the correct sort when sorting by ascending creation date', async function () { | ||
147 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt') | ||
148 | expect(res.body.total).to.equal(2) | ||
149 | |||
150 | const blacklistedVideos = res.body.data | ||
151 | expect(blacklistedVideos).to.be.an('array') | ||
152 | expect(blacklistedVideos.length).to.equal(2) | ||
153 | |||
154 | const result = orderBy(res.body.data, [ 'createdAt' ]) | ||
155 | |||
156 | expect(blacklistedVideos).to.deep.equal(result) | ||
157 | }) | ||
55 | }) | 158 | }) |
56 | 159 | ||
57 | it('Should not have the video blacklisted in videos list on server 1', async function () { | 160 | describe('When updating blacklisted videos', function () { |
58 | const res = await getVideosList(servers[0].url) | 161 | it('Should change the reason', async function () { |
162 | await updateVideoBlacklist(servers[0].url, servers[0].accessToken, videoId, 'my super reason updated') | ||
163 | |||
164 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
165 | const video = res.body.data.find(b => b.video.id === videoId) | ||
59 | 166 | ||
60 | expect(res.body.total).to.equal(0) | 167 | expect(video.reason).to.equal('my super reason updated') |
61 | expect(res.body.data).to.be.an('array') | 168 | }) |
62 | expect(res.body.data.length).to.equal(0) | ||
63 | }) | 169 | }) |
64 | 170 | ||
65 | it('Should not have the video blacklisted in videos search on server 1', async function () { | 171 | describe('When listing my videos', function () { |
66 | const res = await searchVideo(servers[0].url, 'name') | 172 | it('Should display blacklisted videos', async function () { |
173 | await blacklistVideosOnServer(servers[1]) | ||
174 | |||
175 | const res = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 5) | ||
67 | 176 | ||
68 | expect(res.body.total).to.equal(0) | 177 | expect(res.body.total).to.equal(2) |
69 | expect(res.body.data).to.be.an('array') | 178 | expect(res.body.data).to.have.lengthOf(2) |
70 | expect(res.body.data.length).to.equal(0) | 179 | |
180 | for (const video of res.body.data) { | ||
181 | expect(video.blacklisted).to.be.true | ||
182 | expect(video.blacklistedReason).to.equal('super reason') | ||
183 | } | ||
184 | }) | ||
71 | }) | 185 | }) |
72 | 186 | ||
73 | it('Should have the blacklisted video in videos list on server 2', async function () { | 187 | describe('When removing a blacklisted video', function () { |
74 | const res = await getVideosList(servers[1].url) | 188 | let videoToRemove: VideoBlacklist |
189 | let blacklist = [] | ||
190 | |||
191 | it('Should not have any video in videos list on server 1', async function () { | ||
192 | const res = await getVideosList(servers[0].url) | ||
193 | expect(res.body.total).to.equal(0) | ||
194 | expect(res.body.data).to.be.an('array') | ||
195 | expect(res.body.data.length).to.equal(0) | ||
196 | }) | ||
197 | |||
198 | it('Should remove a video from the blacklist on server 1', async function () { | ||
199 | // Get one video in the blacklist | ||
200 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
201 | videoToRemove = res.body.data[0] | ||
202 | blacklist = res.body.data.slice(1) | ||
203 | |||
204 | // Remove it | ||
205 | await removeVideoFromBlacklist(servers[0].url, servers[0].accessToken, videoToRemove.video.id) | ||
206 | }) | ||
207 | |||
208 | it('Should have the ex-blacklisted video in videos list on server 1', async function () { | ||
209 | const res = await getVideosList(servers[0].url) | ||
210 | expect(res.body.total).to.equal(1) | ||
211 | |||
212 | const videos = res.body.data | ||
213 | expect(videos).to.be.an('array') | ||
214 | expect(videos.length).to.equal(1) | ||
215 | |||
216 | expect(videos[0].name).to.equal(videoToRemove.video.name) | ||
217 | expect(videos[0].id).to.equal(videoToRemove.video.id) | ||
218 | }) | ||
219 | |||
220 | it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () { | ||
221 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, '-name') | ||
222 | expect(res.body.total).to.equal(1) | ||
75 | 223 | ||
76 | expect(res.body.total).to.equal(1) | 224 | const videos = res.body.data |
77 | expect(res.body.data).to.be.an('array') | 225 | expect(videos).to.be.an('array') |
78 | expect(res.body.data.length).to.equal(1) | 226 | expect(videos.length).to.equal(1) |
227 | expect(videos).to.deep.equal(blacklist) | ||
228 | }) | ||
79 | }) | 229 | }) |
80 | 230 | ||
81 | it('Should have the video blacklisted in videos search on server 2', async function () { | 231 | describe('When blacklisting local videos', function () { |
82 | const res = await searchVideo(servers[1].url, 'name') | 232 | let video3UUID: string |
233 | let video4UUID: string | ||
234 | |||
235 | before(async function () { | ||
236 | this.timeout(10000) | ||
237 | |||
238 | { | ||
239 | const res = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'Video 3' }) | ||
240 | video3UUID = res.body.video.uuid | ||
241 | } | ||
242 | { | ||
243 | const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'Video 4' }) | ||
244 | video4UUID = res.body.video.uuid | ||
245 | } | ||
246 | |||
247 | await waitJobs(servers) | ||
248 | }) | ||
249 | |||
250 | it('Should blacklist video 3 and keep it federated', async function () { | ||
251 | this.timeout(10000) | ||
252 | |||
253 | await addVideoToBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video3UUID, 'super reason', false) | ||
254 | |||
255 | await waitJobs(servers) | ||
256 | |||
257 | { | ||
258 | const res = await getVideosList(servers[ 0 ].url) | ||
259 | expect(res.body.data.find(v => v.uuid === video3UUID)).to.be.undefined | ||
260 | } | ||
261 | |||
262 | { | ||
263 | const res = await getVideosList(servers[ 1 ].url) | ||
264 | expect(res.body.data.find(v => v.uuid === video3UUID)).to.not.be.undefined | ||
265 | } | ||
266 | }) | ||
267 | |||
268 | it('Should unfederate the video', async function () { | ||
269 | this.timeout(10000) | ||
270 | |||
271 | await addVideoToBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID, 'super reason', true) | ||
272 | |||
273 | await waitJobs(servers) | ||
274 | |||
275 | for (const server of servers) { | ||
276 | const res = await getVideosList(server.url) | ||
277 | expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined | ||
278 | } | ||
279 | }) | ||
280 | |||
281 | it('Should have the video unfederated even after an Update AP message', async function () { | ||
282 | this.timeout(10000) | ||
283 | |||
284 | await updateVideo(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID, { description: 'super description' }) | ||
285 | |||
286 | await waitJobs(servers) | ||
287 | |||
288 | for (const server of servers) { | ||
289 | const res = await getVideosList(server.url) | ||
290 | expect(res.body.data.find(v => v.uuid === video4UUID)).to.be.undefined | ||
291 | } | ||
292 | }) | ||
293 | |||
294 | it('Should have the correct video blacklist unfederate attribute', async function () { | ||
295 | const res = await getSortedBlacklistedVideosList(servers[0].url, servers[0].accessToken, 'createdAt') | ||
296 | |||
297 | const blacklistedVideos: VideoBlacklist[] = res.body.data | ||
298 | const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID) | ||
299 | const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID) | ||
300 | |||
301 | expect(video3Blacklisted.unfederated).to.be.false | ||
302 | expect(video4Blacklisted.unfederated).to.be.true | ||
303 | }) | ||
304 | |||
305 | it('Should remove the video from blacklist and refederate the video', async function () { | ||
306 | this.timeout(10000) | ||
307 | |||
308 | await removeVideoFromBlacklist(servers[ 0 ].url, servers[ 0 ].accessToken, video4UUID) | ||
309 | |||
310 | await waitJobs(servers) | ||
311 | |||
312 | for (const server of servers) { | ||
313 | const res = await getVideosList(server.url) | ||
314 | expect(res.body.data.find(v => v.uuid === video4UUID)).to.not.be.undefined | ||
315 | } | ||
316 | }) | ||
83 | 317 | ||
84 | expect(res.body.total).to.equal(1) | ||
85 | expect(res.body.data).to.be.an('array') | ||
86 | expect(res.body.data.length).to.equal(1) | ||
87 | }) | 318 | }) |
88 | 319 | ||
89 | after(async function () { | 320 | after(async function () { |
diff --git a/server/tests/api/videos/video-captions.ts b/server/tests/api/videos/video-captions.ts index 6e441410d..57bee713f 100644 --- a/server/tests/api/videos/video-captions.ts +++ b/server/tests/api/videos/video-captions.ts | |||
@@ -2,10 +2,17 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { checkVideoFilesWereRemoved, doubleFollow, flushAndRunMultipleServers, removeVideo, uploadVideo, wait } from '../../utils' | 5 | import { |
6 | import { flushTests, killallServers, ServerInfo, setAccessTokensToServers } from '../../utils/index' | 6 | checkVideoFilesWereRemoved, |
7 | import { waitJobs } from '../../utils/server/jobs' | 7 | doubleFollow, |
8 | import { createVideoCaption, deleteVideoCaption, listVideoCaptions, testCaptionFile } from '../../utils/videos/video-captions' | 8 | flushAndRunMultipleServers, |
9 | removeVideo, | ||
10 | uploadVideo, | ||
11 | wait | ||
12 | } from '../../../../shared/utils' | ||
13 | import { flushTests, killallServers, ServerInfo, setAccessTokensToServers } from '../../../../shared/utils/index' | ||
14 | import { waitJobs } from '../../../../shared/utils/server/jobs' | ||
15 | import { createVideoCaption, deleteVideoCaption, listVideoCaptions, testCaptionFile } from '../../../../shared/utils/videos/video-captions' | ||
9 | import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' | 16 | import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model' |
10 | 17 | ||
11 | const expect = chai.expect | 18 | const expect = chai.expect |
diff --git a/server/tests/api/videos/video-change-ownership.ts b/server/tests/api/videos/video-change-ownership.ts index 1578a471d..25675a966 100644 --- a/server/tests/api/videos/video-change-ownership.ts +++ b/server/tests/api/videos/video-change-ownership.ts | |||
@@ -18,8 +18,8 @@ import { | |||
18 | uploadVideo, | 18 | uploadVideo, |
19 | userLogin, | 19 | userLogin, |
20 | getVideo | 20 | getVideo |
21 | } from '../../utils' | 21 | } from '../../../../shared/utils' |
22 | import { waitJobs } from '../../utils/server/jobs' | 22 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
23 | import { User } from '../../../../shared/models/users' | 23 | import { User } from '../../../../shared/models/users' |
24 | import { VideoDetails } from '../../../../shared/models/videos' | 24 | import { VideoDetails } from '../../../../shared/models/videos' |
25 | 25 | ||
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 8138c65d6..63514d69c 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -7,11 +7,13 @@ import { | |||
7 | createUser, | 7 | createUser, |
8 | doubleFollow, | 8 | doubleFollow, |
9 | flushAndRunMultipleServers, | 9 | flushAndRunMultipleServers, |
10 | getVideoChannelVideos, serverLogin, testImage, | 10 | getVideoChannelVideos, |
11 | testImage, | ||
11 | updateVideo, | 12 | updateVideo, |
12 | updateVideoChannelAvatar, | 13 | updateVideoChannelAvatar, |
13 | uploadVideo, wait, userLogin | 14 | uploadVideo, |
14 | } from '../../utils' | 15 | userLogin |
16 | } from '../../../../shared/utils' | ||
15 | import { | 17 | import { |
16 | addVideoChannel, | 18 | addVideoChannel, |
17 | deleteVideoChannel, | 19 | deleteVideoChannel, |
@@ -24,8 +26,8 @@ import { | |||
24 | ServerInfo, | 26 | ServerInfo, |
25 | setAccessTokensToServers, | 27 | setAccessTokensToServers, |
26 | updateVideoChannel | 28 | updateVideoChannel |
27 | } from '../../utils/index' | 29 | } from '../../../../shared/utils/index' |
28 | import { waitJobs } from '../../utils/server/jobs' | 30 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
29 | 31 | ||
30 | const expect = chai.expect | 32 | const expect = chai.expect |
31 | 33 | ||
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts index d6e07c5b3..ce1b17e35 100644 --- a/server/tests/api/videos/video-comments.ts +++ b/server/tests/api/videos/video-comments.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | 5 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' |
6 | import { testImage } from '../../utils' | 6 | import { testImage } from '../../../../shared/utils' |
7 | import { | 7 | import { |
8 | dateIsValid, | 8 | dateIsValid, |
9 | flushTests, | 9 | flushTests, |
@@ -13,14 +13,14 @@ import { | |||
13 | setAccessTokensToServers, | 13 | setAccessTokensToServers, |
14 | updateMyAvatar, | 14 | updateMyAvatar, |
15 | uploadVideo | 15 | uploadVideo |
16 | } from '../../utils/index' | 16 | } from '../../../../shared/utils/index' |
17 | import { | 17 | import { |
18 | addVideoCommentReply, | 18 | addVideoCommentReply, |
19 | addVideoCommentThread, | 19 | addVideoCommentThread, |
20 | deleteVideoComment, | 20 | deleteVideoComment, |
21 | getVideoCommentThreads, | 21 | getVideoCommentThreads, |
22 | getVideoThreadComments | 22 | getVideoThreadComments |
23 | } from '../../utils/videos/video-comments' | 23 | } from '../../../../shared/utils/videos/video-comments' |
24 | 24 | ||
25 | const expect = chai.expect | 25 | const expect = chai.expect |
26 | 26 | ||
diff --git a/server/tests/api/videos/video-description.ts b/server/tests/api/videos/video-description.ts index dd5cd78c0..cbda0b9a6 100644 --- a/server/tests/api/videos/video-description.ts +++ b/server/tests/api/videos/video-description.ts | |||
@@ -12,9 +12,9 @@ import { | |||
12 | setAccessTokensToServers, | 12 | setAccessTokensToServers, |
13 | updateVideo, | 13 | updateVideo, |
14 | uploadVideo | 14 | uploadVideo |
15 | } from '../../utils/index' | 15 | } from '../../../../shared/utils/index' |
16 | import { doubleFollow } from '../../utils/server/follows' | 16 | import { doubleFollow } from '../../../../shared/utils/server/follows' |
17 | import { waitJobs } from '../../utils/server/jobs' | 17 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
18 | 18 | ||
19 | const expect = chai.expect | 19 | const expect = chai.expect |
20 | 20 | ||
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts new file mode 100644 index 000000000..a1214bad1 --- /dev/null +++ b/server/tests/api/videos/video-hls.ts | |||
@@ -0,0 +1,139 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | checkDirectoryIsEmpty, | ||
7 | checkSegmentHash, | ||
8 | checkTmpIsEmpty, | ||
9 | doubleFollow, | ||
10 | flushAndRunMultipleServers, | ||
11 | flushTests, | ||
12 | getPlaylist, | ||
13 | getVideo, | ||
14 | killallServers, | ||
15 | removeVideo, | ||
16 | ServerInfo, | ||
17 | setAccessTokensToServers, | ||
18 | updateVideo, | ||
19 | uploadVideo, | ||
20 | waitJobs | ||
21 | } from '../../../../shared/utils' | ||
22 | import { VideoDetails } from '../../../../shared/models/videos' | ||
23 | import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type' | ||
24 | import { join } from 'path' | ||
25 | |||
26 | const expect = chai.expect | ||
27 | |||
28 | async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string) { | ||
29 | const resolutions = [ 240, 360, 480, 720 ] | ||
30 | |||
31 | for (const server of servers) { | ||
32 | const res = await getVideo(server.url, videoUUID) | ||
33 | const videoDetails: VideoDetails = res.body | ||
34 | |||
35 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) | ||
36 | |||
37 | const hlsPlaylist = videoDetails.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS) | ||
38 | expect(hlsPlaylist).to.not.be.undefined | ||
39 | |||
40 | { | ||
41 | const res2 = await getPlaylist(hlsPlaylist.playlistUrl) | ||
42 | |||
43 | const masterPlaylist = res2.text | ||
44 | |||
45 | expect(masterPlaylist).to.contain('#EXT-X-STREAM-INF:BANDWIDTH=55472,RESOLUTION=640x360,FRAME-RATE=25') | ||
46 | |||
47 | for (const resolution of resolutions) { | ||
48 | expect(masterPlaylist).to.contain(`${resolution}.m3u8`) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | { | ||
53 | for (const resolution of resolutions) { | ||
54 | const res2 = await getPlaylist(`http://localhost:9001/static/playlists/hls/${videoUUID}/${resolution}.m3u8`) | ||
55 | |||
56 | const subPlaylist = res2.text | ||
57 | expect(subPlaylist).to.contain(`${videoUUID}-${resolution}-fragmented.mp4`) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | { | ||
62 | const baseUrl = 'http://localhost:9001/static/playlists/hls' | ||
63 | |||
64 | for (const resolution of resolutions) { | ||
65 | await checkSegmentHash(baseUrl, baseUrl, videoUUID, resolution, hlsPlaylist) | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | describe('Test HLS videos', function () { | ||
72 | let servers: ServerInfo[] = [] | ||
73 | let videoUUID = '' | ||
74 | |||
75 | before(async function () { | ||
76 | this.timeout(120000) | ||
77 | |||
78 | servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: true, hls: { enabled: true } } }) | ||
79 | |||
80 | // Get the access tokens | ||
81 | await setAccessTokensToServers(servers) | ||
82 | |||
83 | // Server 1 and server 2 follow each other | ||
84 | await doubleFollow(servers[0], servers[1]) | ||
85 | }) | ||
86 | |||
87 | it('Should upload a video and transcode it to HLS', async function () { | ||
88 | this.timeout(120000) | ||
89 | |||
90 | { | ||
91 | const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'video 1', fixture: 'video_short.webm' }) | ||
92 | videoUUID = res.body.video.uuid | ||
93 | } | ||
94 | |||
95 | await waitJobs(servers) | ||
96 | |||
97 | await checkHlsPlaylist(servers, videoUUID) | ||
98 | }) | ||
99 | |||
100 | it('Should update the video', async function () { | ||
101 | await updateVideo(servers[0].url, servers[0].accessToken, videoUUID, { name: 'video 1 updated' }) | ||
102 | |||
103 | await waitJobs(servers) | ||
104 | |||
105 | await checkHlsPlaylist(servers, videoUUID) | ||
106 | }) | ||
107 | |||
108 | it('Should delete the video', async function () { | ||
109 | await removeVideo(servers[0].url, servers[0].accessToken, videoUUID) | ||
110 | |||
111 | await waitJobs(servers) | ||
112 | |||
113 | for (const server of servers) { | ||
114 | await getVideo(server.url, videoUUID, 404) | ||
115 | } | ||
116 | }) | ||
117 | |||
118 | it('Should have the playlists/segment deleted from the disk', async function () { | ||
119 | for (const server of servers) { | ||
120 | await checkDirectoryIsEmpty(server, 'videos') | ||
121 | await checkDirectoryIsEmpty(server, join('playlists', 'hls')) | ||
122 | } | ||
123 | }) | ||
124 | |||
125 | it('Should have an empty tmp directory', async function () { | ||
126 | for (const server of servers) { | ||
127 | await checkTmpIsEmpty(server) | ||
128 | } | ||
129 | }) | ||
130 | |||
131 | after(async function () { | ||
132 | killallServers(servers) | ||
133 | |||
134 | // Keep the logs if the test failed | ||
135 | if (this['ok']) { | ||
136 | await flushTests() | ||
137 | } | ||
138 | }) | ||
139 | }) | ||
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts index b7866d529..cd4988553 100644 --- a/server/tests/api/videos/video-imports.ts +++ b/server/tests/api/videos/video-imports.ts | |||
@@ -14,9 +14,9 @@ import { | |||
14 | killallServers, | 14 | killallServers, |
15 | ServerInfo, | 15 | ServerInfo, |
16 | setAccessTokensToServers | 16 | setAccessTokensToServers |
17 | } from '../../utils' | 17 | } from '../../../../shared/utils' |
18 | import { waitJobs } from '../../utils/server/jobs' | 18 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
19 | import { getMagnetURI, getYoutubeVideoUrl, importVideo, getMyVideoImports } from '../../utils/videos/video-imports' | 19 | import { getMagnetURI, getYoutubeVideoUrl, importVideo, getMyVideoImports } from '../../../../shared/utils/videos/video-imports' |
20 | 20 | ||
21 | const expect = chai.expect | 21 | const expect = chai.expect |
22 | 22 | ||
@@ -30,7 +30,7 @@ describe('Test video imports', function () { | |||
30 | const videoHttp: VideoDetails = resHttp.body | 30 | const videoHttp: VideoDetails = resHttp.body |
31 | 31 | ||
32 | expect(videoHttp.name).to.equal('small video - youtube') | 32 | expect(videoHttp.name).to.equal('small video - youtube') |
33 | expect(videoHttp.category.label).to.equal('News') | 33 | expect(videoHttp.category.label).to.equal('News & Politics') |
34 | expect(videoHttp.licence.label).to.equal('Attribution') | 34 | expect(videoHttp.licence.label).to.equal('Attribution') |
35 | expect(videoHttp.language.label).to.equal('Unknown') | 35 | expect(videoHttp.language.label).to.equal('Unknown') |
36 | expect(videoHttp.nsfw).to.be.false | 36 | expect(videoHttp.nsfw).to.be.false |
diff --git a/server/tests/api/videos/video-nsfw.ts b/server/tests/api/videos/video-nsfw.ts index eab7a6991..df1ee2eb9 100644 --- a/server/tests/api/videos/video-nsfw.ts +++ b/server/tests/api/videos/video-nsfw.ts | |||
@@ -2,10 +2,17 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { flushTests, getVideosList, killallServers, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../utils/index' | 5 | import { |
6 | import { userLogin } from '../../utils/users/login' | 6 | flushTests, |
7 | import { createUser } from '../../utils/users/users' | 7 | getVideosList, |
8 | import { getMyVideos } from '../../utils/videos/videos' | 8 | killallServers, |
9 | ServerInfo, | ||
10 | setAccessTokensToServers, | ||
11 | uploadVideo | ||
12 | } from '../../../../shared/utils/index' | ||
13 | import { userLogin } from '../../../../shared/utils/users/login' | ||
14 | import { createUser } from '../../../../shared/utils/users/users' | ||
15 | import { getMyVideos } from '../../../../shared/utils/videos/videos' | ||
9 | import { | 16 | import { |
10 | getAccountVideos, | 17 | getAccountVideos, |
11 | getConfig, | 18 | getConfig, |
@@ -18,7 +25,7 @@ import { | |||
18 | searchVideoWithToken, | 25 | searchVideoWithToken, |
19 | updateCustomConfig, | 26 | updateCustomConfig, |
20 | updateMyUser | 27 | updateMyUser |
21 | } from '../../utils' | 28 | } from '../../../../shared/utils' |
22 | import { ServerConfig } from '../../../../shared/models' | 29 | import { ServerConfig } from '../../../../shared/models' |
23 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' | 30 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' |
24 | import { User } from '../../../../shared/models/users' | 31 | import { User } from '../../../../shared/models/users' |
diff --git a/server/tests/api/videos/video-privacy.ts b/server/tests/api/videos/video-privacy.ts index 9fefca7e3..0b4e66369 100644 --- a/server/tests/api/videos/video-privacy.ts +++ b/server/tests/api/videos/video-privacy.ts | |||
@@ -10,12 +10,12 @@ import { | |||
10 | ServerInfo, | 10 | ServerInfo, |
11 | setAccessTokensToServers, | 11 | setAccessTokensToServers, |
12 | uploadVideo | 12 | uploadVideo |
13 | } from '../../utils/index' | 13 | } from '../../../../shared/utils/index' |
14 | import { doubleFollow } from '../../utils/server/follows' | 14 | import { doubleFollow } from '../../../../shared/utils/server/follows' |
15 | import { userLogin } from '../../utils/users/login' | 15 | import { userLogin } from '../../../../shared/utils/users/login' |
16 | import { createUser } from '../../utils/users/users' | 16 | import { createUser } from '../../../../shared/utils/users/users' |
17 | import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../utils/videos/videos' | 17 | import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/utils/videos/videos' |
18 | import { waitJobs } from '../../utils/server/jobs' | 18 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
19 | 19 | ||
20 | const expect = chai.expect | 20 | const expect = chai.expect |
21 | 21 | ||
diff --git a/server/tests/api/videos/video-schedule-update.ts b/server/tests/api/videos/video-schedule-update.ts index a260fa4da..632c4244c 100644 --- a/server/tests/api/videos/video-schedule-update.ts +++ b/server/tests/api/videos/video-schedule-update.ts | |||
@@ -15,9 +15,8 @@ import { | |||
15 | updateVideo, | 15 | updateVideo, |
16 | uploadVideo, | 16 | uploadVideo, |
17 | wait | 17 | wait |
18 | } from '../../utils' | 18 | } from '../../../../shared/utils' |
19 | import { join } from 'path' | 19 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
20 | import { waitJobs } from '../../utils/server/jobs' | ||
21 | 20 | ||
22 | const expect = chai.expect | 21 | const expect = chai.expect |
23 | 22 | ||
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts index 0f83d4d57..eefd32ef8 100644 --- a/server/tests/api/videos/video-transcoder.ts +++ b/server/tests/api/videos/video-transcoder.ts | |||
@@ -3,13 +3,13 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { omit } from 'lodash' | 5 | import { omit } from 'lodash' |
6 | import * as ffmpeg from 'fluent-ffmpeg' | 6 | import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos' |
7 | import { VideoDetails, VideoState } from '../../../../shared/models/videos' | 7 | import { audio, getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils' |
8 | import { getVideoFileFPS, audio } from '../../../helpers/ffmpeg-utils' | ||
9 | import { | 8 | import { |
10 | buildAbsoluteFixturePath, | 9 | buildAbsoluteFixturePath, |
11 | doubleFollow, | 10 | doubleFollow, |
12 | flushAndRunMultipleServers, | 11 | flushAndRunMultipleServers, |
12 | generateHighBitrateVideo, | ||
13 | getMyVideos, | 13 | getMyVideos, |
14 | getVideo, | 14 | getVideo, |
15 | getVideosList, | 15 | getVideosList, |
@@ -19,9 +19,10 @@ import { | |||
19 | setAccessTokensToServers, | 19 | setAccessTokensToServers, |
20 | uploadVideo, | 20 | uploadVideo, |
21 | webtorrentAdd | 21 | webtorrentAdd |
22 | } from '../../utils' | 22 | } from '../../../../shared/utils' |
23 | import { join } from 'path' | 23 | import { extname, join } from 'path' |
24 | import { waitJobs } from '../../utils/server/jobs' | 24 | import { waitJobs } from '../../../../shared/utils/server/jobs' |
25 | import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants' | ||
25 | 26 | ||
26 | const expect = chai.expect | 27 | const expect = chai.expect |
27 | 28 | ||
@@ -121,7 +122,7 @@ describe('Test video transcoding', function () { | |||
121 | expect(videoDetails.files).to.have.lengthOf(4) | 122 | expect(videoDetails.files).to.have.lengthOf(4) |
122 | 123 | ||
123 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 124 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
124 | const probe = await audio.get(ffmpeg, path) | 125 | const probe = await audio.get(path) |
125 | 126 | ||
126 | if (probe.audioStream) { | 127 | if (probe.audioStream) { |
127 | expect(probe.audioStream[ 'codec_name' ]).to.be.equal('aac') | 128 | expect(probe.audioStream[ 'codec_name' ]).to.be.equal('aac') |
@@ -152,7 +153,7 @@ describe('Test video transcoding', function () { | |||
152 | 153 | ||
153 | expect(videoDetails.files).to.have.lengthOf(4) | 154 | expect(videoDetails.files).to.have.lengthOf(4) |
154 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 155 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
155 | const probe = await audio.get(ffmpeg, path) | 156 | const probe = await audio.get(path) |
156 | expect(probe).to.not.have.property('audioStream') | 157 | expect(probe).to.not.have.property('audioStream') |
157 | } | 158 | } |
158 | }) | 159 | }) |
@@ -177,9 +178,9 @@ describe('Test video transcoding', function () { | |||
177 | 178 | ||
178 | expect(videoDetails.files).to.have.lengthOf(4) | 179 | expect(videoDetails.files).to.have.lengthOf(4) |
179 | const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) | 180 | const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) |
180 | const fixtureVideoProbe = await audio.get(ffmpeg, fixturePath) | 181 | const fixtureVideoProbe = await audio.get(fixturePath) |
181 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') | 182 | const path = join(root(), 'test2', 'videos', video.uuid + '-240.mp4') |
182 | const videoProbe = await audio.get(ffmpeg, path) | 183 | const videoProbe = await audio.get(path) |
183 | if (videoProbe.audioStream && fixtureVideoProbe.audioStream) { | 184 | if (videoProbe.audioStream && fixtureVideoProbe.audioStream) { |
184 | const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ] | 185 | const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ] |
185 | expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit)) | 186 | expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit)) |
@@ -228,7 +229,7 @@ describe('Test video transcoding', function () { | |||
228 | } | 229 | } |
229 | }) | 230 | }) |
230 | 231 | ||
231 | it('Should wait transcoding before publishing the video', async function () { | 232 | it('Should wait for transcoding before publishing the video', async function () { |
232 | this.timeout(80000) | 233 | this.timeout(80000) |
233 | 234 | ||
234 | { | 235 | { |
@@ -281,6 +282,73 @@ describe('Test video transcoding', function () { | |||
281 | } | 282 | } |
282 | }) | 283 | }) |
283 | 284 | ||
285 | it('Should respect maximum bitrate values', async function () { | ||
286 | this.timeout(160000) | ||
287 | |||
288 | let tempFixturePath: string | ||
289 | |||
290 | { | ||
291 | tempFixturePath = await generateHighBitrateVideo() | ||
292 | |||
293 | const bitrate = await getVideoFileBitrate(tempFixturePath) | ||
294 | expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS)) | ||
295 | } | ||
296 | |||
297 | const videoAttributes = { | ||
298 | name: 'high bitrate video', | ||
299 | description: 'high bitrate video', | ||
300 | fixture: tempFixturePath | ||
301 | } | ||
302 | |||
303 | await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) | ||
304 | |||
305 | await waitJobs(servers) | ||
306 | |||
307 | for (const server of servers) { | ||
308 | const res = await getVideosList(server.url) | ||
309 | |||
310 | const video = res.body.data.find(v => v.name === videoAttributes.name) | ||
311 | |||
312 | for (const resolution of ['240', '360', '480', '720', '1080']) { | ||
313 | const path = join(root(), 'test2', 'videos', video.uuid + '-' + resolution + '.mp4') | ||
314 | const bitrate = await getVideoFileBitrate(path) | ||
315 | const fps = await getVideoFileFPS(path) | ||
316 | const resolution2 = await getVideoFileResolution(path) | ||
317 | |||
318 | expect(resolution2.videoFileResolution.toString()).to.equal(resolution) | ||
319 | expect(bitrate).to.be.below(getMaxBitrate(resolution2.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) | ||
320 | } | ||
321 | } | ||
322 | }) | ||
323 | |||
324 | it('Should accept and transcode additional extensions', async function () { | ||
325 | this.timeout(300000) | ||
326 | |||
327 | for (const fixture of [ 'video_short.mkv', 'video_short.avi' ]) { | ||
328 | const videoAttributes = { | ||
329 | name: fixture, | ||
330 | fixture | ||
331 | } | ||
332 | |||
333 | await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, videoAttributes) | ||
334 | |||
335 | await waitJobs(servers) | ||
336 | |||
337 | for (const server of servers) { | ||
338 | const res = await getVideosList(server.url) | ||
339 | |||
340 | const video = res.body.data.find(v => v.name === videoAttributes.name) | ||
341 | const res2 = await getVideo(server.url, video.id) | ||
342 | const videoDetails = res2.body | ||
343 | |||
344 | expect(videoDetails.files).to.have.lengthOf(4) | ||
345 | |||
346 | const magnetUri = videoDetails.files[ 0 ].magnetUri | ||
347 | expect(magnetUri).to.contain('.mp4') | ||
348 | } | ||
349 | } | ||
350 | }) | ||
351 | |||
284 | after(async function () { | 352 | after(async function () { |
285 | killallServers(servers) | 353 | killallServers(servers) |
286 | }) | 354 | }) |
diff --git a/server/tests/api/videos/videos-filter.ts b/server/tests/api/videos/videos-filter.ts new file mode 100644 index 000000000..59e37ad86 --- /dev/null +++ b/server/tests/api/videos/videos-filter.ts | |||
@@ -0,0 +1,130 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { | ||
6 | createUser, | ||
7 | doubleFollow, | ||
8 | flushAndRunMultipleServers, | ||
9 | flushTests, | ||
10 | killallServers, | ||
11 | makeGetRequest, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | uploadVideo, | ||
15 | userLogin | ||
16 | } from '../../../../shared/utils' | ||
17 | import { Video, VideoPrivacy } from '../../../../shared/models/videos' | ||
18 | import { UserRole } from '../../../../shared/models/users' | ||
19 | |||
20 | const expect = chai.expect | ||
21 | |||
22 | async function getVideosNames (server: ServerInfo, token: string, filter: string, statusCodeExpected = 200) { | ||
23 | const paths = [ | ||
24 | '/api/v1/video-channels/root_channel/videos', | ||
25 | '/api/v1/accounts/root/videos', | ||
26 | '/api/v1/videos', | ||
27 | '/api/v1/search/videos' | ||
28 | ] | ||
29 | |||
30 | const videosResults: Video[][] = [] | ||
31 | |||
32 | for (const path of paths) { | ||
33 | const res = await makeGetRequest({ | ||
34 | url: server.url, | ||
35 | path, | ||
36 | token, | ||
37 | query: { | ||
38 | sort: 'createdAt', | ||
39 | filter | ||
40 | }, | ||
41 | statusCodeExpected | ||
42 | }) | ||
43 | |||
44 | videosResults.push(res.body.data.map(v => v.name)) | ||
45 | } | ||
46 | |||
47 | return videosResults | ||
48 | } | ||
49 | |||
50 | describe('Test videos filter validator', function () { | ||
51 | let servers: ServerInfo[] | ||
52 | |||
53 | // --------------------------------------------------------------- | ||
54 | |||
55 | before(async function () { | ||
56 | this.timeout(120000) | ||
57 | |||
58 | await flushTests() | ||
59 | |||
60 | servers = await flushAndRunMultipleServers(2) | ||
61 | |||
62 | await setAccessTokensToServers(servers) | ||
63 | |||
64 | for (const server of servers) { | ||
65 | const moderator = { username: 'moderator', password: 'my super password' } | ||
66 | await createUser( | ||
67 | server.url, | ||
68 | server.accessToken, | ||
69 | moderator.username, | ||
70 | moderator.password, | ||
71 | undefined, | ||
72 | undefined, | ||
73 | UserRole.MODERATOR | ||
74 | ) | ||
75 | server['moderatorAccessToken'] = await userLogin(server, moderator) | ||
76 | |||
77 | await uploadVideo(server.url, server.accessToken, { name: 'public ' + server.serverNumber }) | ||
78 | |||
79 | { | ||
80 | const attributes = { name: 'unlisted ' + server.serverNumber, privacy: VideoPrivacy.UNLISTED } | ||
81 | await uploadVideo(server.url, server.accessToken, attributes) | ||
82 | } | ||
83 | |||
84 | { | ||
85 | const attributes = { name: 'private ' + server.serverNumber, privacy: VideoPrivacy.PRIVATE } | ||
86 | await uploadVideo(server.url, server.accessToken, attributes) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | await doubleFollow(servers[0], servers[1]) | ||
91 | }) | ||
92 | |||
93 | describe('Check videos filter', function () { | ||
94 | |||
95 | it('Should display local videos', async function () { | ||
96 | for (const server of servers) { | ||
97 | const namesResults = await getVideosNames(server, server.accessToken, 'local') | ||
98 | for (const names of namesResults) { | ||
99 | expect(names).to.have.lengthOf(1) | ||
100 | expect(names[ 0 ]).to.equal('public ' + server.serverNumber) | ||
101 | } | ||
102 | } | ||
103 | }) | ||
104 | |||
105 | it('Should display all local videos by the admin or the moderator', async function () { | ||
106 | for (const server of servers) { | ||
107 | for (const token of [ server.accessToken, server['moderatorAccessToken'] ]) { | ||
108 | |||
109 | const namesResults = await getVideosNames(server, token, 'all-local') | ||
110 | for (const names of namesResults) { | ||
111 | expect(names).to.have.lengthOf(3) | ||
112 | |||
113 | expect(names[ 0 ]).to.equal('public ' + server.serverNumber) | ||
114 | expect(names[ 1 ]).to.equal('unlisted ' + server.serverNumber) | ||
115 | expect(names[ 2 ]).to.equal('private ' + server.serverNumber) | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | }) | ||
120 | }) | ||
121 | |||
122 | after(async function () { | ||
123 | killallServers(servers) | ||
124 | |||
125 | // Keep the logs if the test failed | ||
126 | if (this['ok']) { | ||
127 | await flushTests() | ||
128 | } | ||
129 | }) | ||
130 | }) | ||
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts index 6d289b288..f654a422b 100644 --- a/server/tests/api/videos/videos-history.ts +++ b/server/tests/api/videos/videos-history.ts | |||
@@ -3,17 +3,21 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { | 5 | import { |
6 | createUser, | ||
6 | flushTests, | 7 | flushTests, |
7 | getVideosListWithToken, | 8 | getVideosListWithToken, |
8 | getVideoWithToken, | 9 | getVideoWithToken, |
9 | killallServers, makePutBodyRequest, | 10 | killallServers, |
10 | runServer, searchVideoWithToken, | 11 | runServer, |
12 | searchVideoWithToken, | ||
11 | ServerInfo, | 13 | ServerInfo, |
12 | setAccessTokensToServers, | 14 | setAccessTokensToServers, |
13 | uploadVideo | 15 | updateMyUser, |
14 | } from '../../utils' | 16 | uploadVideo, |
17 | userLogin | ||
18 | } from '../../../../shared/utils' | ||
15 | import { Video, VideoDetails } from '../../../../shared/models/videos' | 19 | import { Video, VideoDetails } from '../../../../shared/models/videos' |
16 | import { userWatchVideo } from '../../utils/videos/video-history' | 20 | import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/utils/videos/video-history' |
17 | 21 | ||
18 | const expect = chai.expect | 22 | const expect = chai.expect |
19 | 23 | ||
@@ -22,6 +26,8 @@ describe('Test videos history', function () { | |||
22 | let video1UUID: string | 26 | let video1UUID: string |
23 | let video2UUID: string | 27 | let video2UUID: string |
24 | let video3UUID: string | 28 | let video3UUID: string |
29 | let video3WatchedDate: Date | ||
30 | let userAccessToken: string | ||
25 | 31 | ||
26 | before(async function () { | 32 | before(async function () { |
27 | this.timeout(30000) | 33 | this.timeout(30000) |
@@ -46,6 +52,13 @@ describe('Test videos history', function () { | |||
46 | const res = await uploadVideo(server.url, server.accessToken, { name: 'video 3' }) | 52 | const res = await uploadVideo(server.url, server.accessToken, { name: 'video 3' }) |
47 | video3UUID = res.body.video.uuid | 53 | video3UUID = res.body.video.uuid |
48 | } | 54 | } |
55 | |||
56 | const user = { | ||
57 | username: 'user_1', | ||
58 | password: 'super password' | ||
59 | } | ||
60 | await createUser(server.url, server.accessToken, user.username, user.password) | ||
61 | userAccessToken = await userLogin(server, user) | ||
49 | }) | 62 | }) |
50 | 63 | ||
51 | it('Should get videos, without watching history', async function () { | 64 | it('Should get videos, without watching history', async function () { |
@@ -62,8 +75,8 @@ describe('Test videos history', function () { | |||
62 | }) | 75 | }) |
63 | 76 | ||
64 | it('Should watch the first and second video', async function () { | 77 | it('Should watch the first and second video', async function () { |
65 | await userWatchVideo(server.url, server.accessToken, video1UUID, 3) | ||
66 | await userWatchVideo(server.url, server.accessToken, video2UUID, 8) | 78 | await userWatchVideo(server.url, server.accessToken, video2UUID, 8) |
79 | await userWatchVideo(server.url, server.accessToken, video1UUID, 3) | ||
67 | }) | 80 | }) |
68 | 81 | ||
69 | it('Should return the correct history when listing, searching and getting videos', async function () { | 82 | it('Should return the correct history when listing, searching and getting videos', async function () { |
@@ -117,6 +130,68 @@ describe('Test videos history', function () { | |||
117 | } | 130 | } |
118 | }) | 131 | }) |
119 | 132 | ||
133 | it('Should have these videos when listing my history', async function () { | ||
134 | video3WatchedDate = new Date() | ||
135 | await userWatchVideo(server.url, server.accessToken, video3UUID, 2) | ||
136 | |||
137 | const res = await listMyVideosHistory(server.url, server.accessToken) | ||
138 | |||
139 | expect(res.body.total).to.equal(3) | ||
140 | |||
141 | const videos: Video[] = res.body.data | ||
142 | expect(videos[0].name).to.equal('video 3') | ||
143 | expect(videos[1].name).to.equal('video 1') | ||
144 | expect(videos[2].name).to.equal('video 2') | ||
145 | }) | ||
146 | |||
147 | it('Should not have videos history on another user', async function () { | ||
148 | const res = await listMyVideosHistory(server.url, userAccessToken) | ||
149 | |||
150 | expect(res.body.total).to.equal(0) | ||
151 | expect(res.body.data).to.have.lengthOf(0) | ||
152 | }) | ||
153 | |||
154 | it('Should clear my history', async function () { | ||
155 | await removeMyVideosHistory(server.url, server.accessToken, video3WatchedDate.toISOString()) | ||
156 | }) | ||
157 | |||
158 | it('Should have my history cleared', async function () { | ||
159 | const res = await listMyVideosHistory(server.url, server.accessToken) | ||
160 | |||
161 | expect(res.body.total).to.equal(1) | ||
162 | |||
163 | const videos: Video[] = res.body.data | ||
164 | expect(videos[0].name).to.equal('video 3') | ||
165 | }) | ||
166 | |||
167 | it('Should disable videos history', async function () { | ||
168 | await updateMyUser({ | ||
169 | url: server.url, | ||
170 | accessToken: server.accessToken, | ||
171 | videosHistoryEnabled: false | ||
172 | }) | ||
173 | |||
174 | await userWatchVideo(server.url, server.accessToken, video2UUID, 8, 409) | ||
175 | }) | ||
176 | |||
177 | it('Should re-enable videos history', async function () { | ||
178 | await updateMyUser({ | ||
179 | url: server.url, | ||
180 | accessToken: server.accessToken, | ||
181 | videosHistoryEnabled: true | ||
182 | }) | ||
183 | |||
184 | await userWatchVideo(server.url, server.accessToken, video1UUID, 8) | ||
185 | |||
186 | const res = await listMyVideosHistory(server.url, server.accessToken) | ||
187 | |||
188 | expect(res.body.total).to.equal(2) | ||
189 | |||
190 | const videos: Video[] = res.body.data | ||
191 | expect(videos[0].name).to.equal('video 1') | ||
192 | expect(videos[1].name).to.equal('video 3') | ||
193 | }) | ||
194 | |||
120 | after(async function () { | 195 | after(async function () { |
121 | killallServers([ server ]) | 196 | killallServers([ server ]) |
122 | 197 | ||
diff --git a/server/tests/api/videos/videos-overview.ts b/server/tests/api/videos/videos-overview.ts index 7d1f29c92..7221bcae6 100644 --- a/server/tests/api/videos/videos-overview.ts +++ b/server/tests/api/videos/videos-overview.ts | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { flushTests, killallServers, runServer, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../utils' | 5 | import { flushTests, killallServers, runServer, ServerInfo, setAccessTokensToServers, uploadVideo } from '../../../../shared/utils' |
6 | import { getVideosOverview } from '../../utils/overviews/overviews' | 6 | import { getVideosOverview } from '../../../../shared/utils/overviews/overviews' |
7 | import { VideosOverview } from '../../../../shared/models/overviews' | 7 | import { VideosOverview } from '../../../../shared/models/overviews' |
8 | 8 | ||
9 | const expect = chai.expect | 9 | const expect = chai.expect |
diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts index 13bcfd209..4acda47b1 100644 --- a/server/tests/cli/create-import-video-file-job.ts +++ b/server/tests/cli/create-import-video-file-job.ts | |||
@@ -15,8 +15,8 @@ import { | |||
15 | ServerInfo, | 15 | ServerInfo, |
16 | setAccessTokensToServers, | 16 | setAccessTokensToServers, |
17 | uploadVideo | 17 | uploadVideo |
18 | } from '../utils' | 18 | } from '../../../shared/utils' |
19 | import { waitJobs } from '../utils/server/jobs' | 19 | import { waitJobs } from '../../../shared/utils/server/jobs' |
20 | 20 | ||
21 | const expect = chai.expect | 21 | const expect = chai.expect |
22 | 22 | ||
diff --git a/server/tests/cli/create-transcoding-job.ts b/server/tests/cli/create-transcoding-job.ts index c2e3840c5..50be5fa19 100644 --- a/server/tests/cli/create-transcoding-job.ts +++ b/server/tests/cli/create-transcoding-job.ts | |||
@@ -15,8 +15,8 @@ import { | |||
15 | ServerInfo, | 15 | ServerInfo, |
16 | setAccessTokensToServers, | 16 | setAccessTokensToServers, |
17 | uploadVideo, wait | 17 | uploadVideo, wait |
18 | } from '../utils' | 18 | } from '../../../shared/utils' |
19 | import { waitJobs } from '../utils/server/jobs' | 19 | import { waitJobs } from '../../../shared/utils/server/jobs' |
20 | 20 | ||
21 | const expect = chai.expect | 21 | const expect = chai.expect |
22 | 22 | ||
diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts index 6201314ce..c6b7ec078 100644 --- a/server/tests/cli/index.ts +++ b/server/tests/cli/index.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | // Order of the tests we want to execute | 1 | // Order of the tests we want to execute |
2 | import './create-import-video-file-job' | 2 | import './create-import-video-file-job' |
3 | import './create-transcoding-job' | 3 | import './create-transcoding-job' |
4 | import './optimize-old-videos' | ||
4 | import './peertube' | 5 | import './peertube' |
5 | import './reset-password' | 6 | import './reset-password' |
6 | import './update-host' | 7 | import './update-host' |
diff --git a/server/tests/cli/optimize-old-videos.ts b/server/tests/cli/optimize-old-videos.ts new file mode 100644 index 000000000..6f6bc25a6 --- /dev/null +++ b/server/tests/cli/optimize-old-videos.ts | |||
@@ -0,0 +1,120 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { getMaxBitrate, Video, VideoDetails, VideoResolution } from '../../../shared/models/videos' | ||
6 | import { | ||
7 | doubleFollow, | ||
8 | execCLI, | ||
9 | flushAndRunMultipleServers, | ||
10 | flushTests, generateHighBitrateVideo, | ||
11 | getEnvCli, | ||
12 | getVideo, | ||
13 | getVideosList, | ||
14 | killallServers, root, | ||
15 | ServerInfo, | ||
16 | setAccessTokensToServers, | ||
17 | uploadVideo, viewVideo, wait | ||
18 | } from '../../../shared/utils' | ||
19 | import { waitJobs } from '../../../shared/utils/server/jobs' | ||
20 | import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../helpers/ffmpeg-utils' | ||
21 | import { VIDEO_TRANSCODING_FPS } from '../../initializers' | ||
22 | import { join } from 'path' | ||
23 | |||
24 | const expect = chai.expect | ||
25 | |||
26 | describe('Test optimize old videos', function () { | ||
27 | let servers: ServerInfo[] = [] | ||
28 | let video1UUID: string | ||
29 | let video2UUID: string | ||
30 | |||
31 | before(async function () { | ||
32 | this.timeout(200000) | ||
33 | |||
34 | await flushTests() | ||
35 | |||
36 | // Run server 2 to have transcoding enabled | ||
37 | servers = await flushAndRunMultipleServers(2) | ||
38 | await setAccessTokensToServers(servers) | ||
39 | |||
40 | await doubleFollow(servers[0], servers[1]) | ||
41 | |||
42 | let tempFixturePath: string | ||
43 | |||
44 | { | ||
45 | tempFixturePath = await generateHighBitrateVideo() | ||
46 | |||
47 | const bitrate = await getVideoFileBitrate(tempFixturePath) | ||
48 | expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS)) | ||
49 | } | ||
50 | |||
51 | // Upload two videos for our needs | ||
52 | const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1', fixture: tempFixturePath }) | ||
53 | video1UUID = res1.body.video.uuid | ||
54 | const res2 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video2', fixture: tempFixturePath }) | ||
55 | video2UUID = res2.body.video.uuid | ||
56 | |||
57 | await waitJobs(servers) | ||
58 | }) | ||
59 | |||
60 | it('Should have two video files on each server', async function () { | ||
61 | this.timeout(30000) | ||
62 | |||
63 | for (const server of servers) { | ||
64 | const res = await getVideosList(server.url) | ||
65 | const videos = res.body.data | ||
66 | expect(videos).to.have.lengthOf(2) | ||
67 | |||
68 | for (const video of videos) { | ||
69 | const res2 = await getVideo(server.url, video.uuid) | ||
70 | const videoDetail: VideoDetails = res2.body | ||
71 | expect(videoDetail.files).to.have.lengthOf(1) | ||
72 | } | ||
73 | } | ||
74 | }) | ||
75 | |||
76 | it('Should run optimize script', async function () { | ||
77 | this.timeout(120000) | ||
78 | |||
79 | const env = getEnvCli(servers[0]) | ||
80 | await execCLI(`${env} npm run optimize-old-videos`) | ||
81 | |||
82 | await waitJobs(servers) | ||
83 | |||
84 | for (const server of servers) { | ||
85 | const res = await getVideosList(server.url) | ||
86 | const videos: Video[] = res.body.data | ||
87 | |||
88 | expect(videos).to.have.lengthOf(2) | ||
89 | |||
90 | for (const video of videos) { | ||
91 | await viewVideo(server.url, video.uuid) | ||
92 | |||
93 | // Refresh video | ||
94 | await waitJobs(servers) | ||
95 | await wait(5000) | ||
96 | await waitJobs(servers) | ||
97 | |||
98 | const res2 = await getVideo(server.url, video.uuid) | ||
99 | const videosDetails: VideoDetails = res2.body | ||
100 | |||
101 | expect(videosDetails.files).to.have.lengthOf(1) | ||
102 | const file = videosDetails.files[0] | ||
103 | |||
104 | expect(file.size).to.be.below(5000000) | ||
105 | |||
106 | const path = join(root(), 'test1', 'videos', video.uuid + '-' + file.resolution.id + '.mp4') | ||
107 | const bitrate = await getVideoFileBitrate(path) | ||
108 | const fps = await getVideoFileFPS(path) | ||
109 | const resolution = await getVideoFileResolution(path) | ||
110 | |||
111 | expect(resolution.videoFileResolution).to.equal(file.resolution.id) | ||
112 | expect(bitrate).to.be.below(getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) | ||
113 | } | ||
114 | } | ||
115 | }) | ||
116 | |||
117 | after(async function () { | ||
118 | killallServers(servers) | ||
119 | }) | ||
120 | }) | ||
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts index 65cb05a1a..e2836d0c3 100644 --- a/server/tests/cli/peertube.ts +++ b/server/tests/cli/peertube.ts | |||
@@ -11,7 +11,7 @@ import { | |||
11 | runServer, | 11 | runServer, |
12 | ServerInfo, | 12 | ServerInfo, |
13 | setAccessTokensToServers | 13 | setAccessTokensToServers |
14 | } from '../utils' | 14 | } from '../../../shared/utils' |
15 | 15 | ||
16 | describe('Test CLI wrapper', function () { | 16 | describe('Test CLI wrapper', function () { |
17 | let server: ServerInfo | 17 | let server: ServerInfo |
@@ -44,6 +44,8 @@ describe('Test CLI wrapper', function () { | |||
44 | }) | 44 | }) |
45 | 45 | ||
46 | after(async function () { | 46 | after(async function () { |
47 | this.timeout(10000) | ||
48 | |||
47 | await execCLI(cmd + ` auth del ${server.url}`) | 49 | await execCLI(cmd + ` auth del ${server.url}`) |
48 | 50 | ||
49 | killallServers([ server ]) | 51 | killallServers([ server ]) |
diff --git a/server/tests/cli/reset-password.ts b/server/tests/cli/reset-password.ts index bf937d1c0..1b65f7e39 100644 --- a/server/tests/cli/reset-password.ts +++ b/server/tests/cli/reset-password.ts | |||
@@ -10,7 +10,7 @@ import { | |||
10 | runServer, | 10 | runServer, |
11 | ServerInfo, | 11 | ServerInfo, |
12 | setAccessTokensToServers | 12 | setAccessTokensToServers |
13 | } from '../utils' | 13 | } from '../../../shared/utils' |
14 | 14 | ||
15 | describe('Test reset password scripts', function () { | 15 | describe('Test reset password scripts', function () { |
16 | let server: ServerInfo | 16 | let server: ServerInfo |
diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts index b89e72ab7..d38bb4331 100644 --- a/server/tests/cli/update-host.ts +++ b/server/tests/cli/update-host.ts | |||
@@ -3,8 +3,8 @@ | |||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { VideoDetails } from '../../../shared/models/videos' | 5 | import { VideoDetails } from '../../../shared/models/videos' |
6 | import { waitJobs } from '../utils/server/jobs' | 6 | import { waitJobs } from '../../../shared/utils/server/jobs' |
7 | import { addVideoCommentThread } from '../utils/videos/video-comments' | 7 | import { addVideoCommentThread } from '../../../shared/utils/videos/video-comments' |
8 | import { | 8 | import { |
9 | addVideoChannel, | 9 | addVideoChannel, |
10 | createUser, | 10 | createUser, |
@@ -21,8 +21,8 @@ import { | |||
21 | ServerInfo, | 21 | ServerInfo, |
22 | setAccessTokensToServers, | 22 | setAccessTokensToServers, |
23 | uploadVideo | 23 | uploadVideo |
24 | } from '../utils' | 24 | } from '../../../shared/utils' |
25 | import { getAccountsList } from '../utils/users/accounts' | 25 | import { getAccountsList } from '../../../shared/utils/users/accounts' |
26 | 26 | ||
27 | const expect = chai.expect | 27 | const expect = chai.expect |
28 | 28 | ||
@@ -86,6 +86,13 @@ describe('Test update host scripts', function () { | |||
86 | const { body } = await makeActivityPubGetRequest(server.url, '/videos/watch/' + video.uuid) | 86 | const { body } = await makeActivityPubGetRequest(server.url, '/videos/watch/' + video.uuid) |
87 | 87 | ||
88 | expect(body.id).to.equal('http://localhost:9002/videos/watch/' + video.uuid) | 88 | expect(body.id).to.equal('http://localhost:9002/videos/watch/' + video.uuid) |
89 | |||
90 | const res = await getVideo(server.url, video.uuid) | ||
91 | const videoDetails: VideoDetails = res.body | ||
92 | |||
93 | expect(videoDetails.trackerUrls[0]).to.include(server.host) | ||
94 | expect(videoDetails.streamingPlaylists[0].playlistUrl).to.include(server.host) | ||
95 | expect(videoDetails.streamingPlaylists[0].segmentsSha256Url).to.include(server.host) | ||
89 | } | 96 | } |
90 | }) | 97 | }) |
91 | 98 | ||
@@ -100,7 +107,7 @@ describe('Test update host scripts', function () { | |||
100 | } | 107 | } |
101 | }) | 108 | }) |
102 | 109 | ||
103 | it('Should have update accounts url', async function () { | 110 | it('Should have updated accounts url', async function () { |
104 | const res = await getAccountsList(server.url) | 111 | const res = await getAccountsList(server.url) |
105 | expect(res.body.total).to.equal(3) | 112 | expect(res.body.total).to.equal(3) |
106 | 113 | ||
@@ -112,7 +119,7 @@ describe('Test update host scripts', function () { | |||
112 | } | 119 | } |
113 | }) | 120 | }) |
114 | 121 | ||
115 | it('Should update torrent hosts', async function () { | 122 | it('Should have updated torrent hosts', async function () { |
116 | this.timeout(30000) | 123 | this.timeout(30000) |
117 | 124 | ||
118 | const res = await getVideosList(server.url) | 125 | const res = await getVideosList(server.url) |
diff --git a/server/tests/client.ts b/server/tests/client.ts index b33a653b1..06b4a9c5a 100644 --- a/server/tests/client.ts +++ b/server/tests/client.ts | |||
@@ -15,7 +15,7 @@ import { | |||
15 | updateCustomConfig, | 15 | updateCustomConfig, |
16 | updateCustomSubConfig, | 16 | updateCustomSubConfig, |
17 | uploadVideo | 17 | uploadVideo |
18 | } from './utils' | 18 | } from '../../shared/utils' |
19 | 19 | ||
20 | const expect = chai.expect | 20 | const expect = chai.expect |
21 | 21 | ||
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts index 28fe3493b..a771474bc 100644 --- a/server/tests/feeds/feeds.ts +++ b/server/tests/feeds/feeds.ts | |||
@@ -13,10 +13,10 @@ import { | |||
13 | ServerInfo, | 13 | ServerInfo, |
14 | setAccessTokensToServers, | 14 | setAccessTokensToServers, |
15 | uploadVideo, userLogin | 15 | uploadVideo, userLogin |
16 | } from '../utils' | 16 | } from '../../../shared/utils' |
17 | import * as libxmljs from 'libxmljs' | 17 | import * as libxmljs from 'libxmljs' |
18 | import { addVideoCommentThread } from '../utils/videos/video-comments' | 18 | import { addVideoCommentThread } from '../../../shared/utils/videos/video-comments' |
19 | import { waitJobs } from '../utils/server/jobs' | 19 | import { waitJobs } from '../../../shared/utils/server/jobs' |
20 | import { User } from '../../../shared/models/users' | 20 | import { User } from '../../../shared/models/users' |
21 | 21 | ||
22 | chai.use(require('chai-xml')) | 22 | chai.use(require('chai-xml')) |
diff --git a/server/tests/fixtures/video_short.avi b/server/tests/fixtures/video_short.avi new file mode 100644 index 000000000..88979cab2 --- /dev/null +++ b/server/tests/fixtures/video_short.avi | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short.mkv b/server/tests/fixtures/video_short.mkv new file mode 100644 index 000000000..a67f4f806 --- /dev/null +++ b/server/tests/fixtures/video_short.mkv | |||
Binary files differ | |||
diff --git a/server/tests/fixtures/video_short_240p.mp4 b/server/tests/fixtures/video_short_240p.mp4 new file mode 100644 index 000000000..db074940b --- /dev/null +++ b/server/tests/fixtures/video_short_240p.mp4 | |||
Binary files differ | |||
diff --git a/server/tests/helpers/comment-model.ts b/server/tests/helpers/comment-model.ts new file mode 100644 index 000000000..76bb0f212 --- /dev/null +++ b/server/tests/helpers/comment-model.ts | |||
@@ -0,0 +1,25 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { VideoCommentModel } from '../../models/video/video-comment' | ||
6 | |||
7 | const expect = chai.expect | ||
8 | |||
9 | class CommentMock { | ||
10 | text: string | ||
11 | |||
12 | extractMentions = VideoCommentModel.prototype.extractMentions | ||
13 | } | ||
14 | |||
15 | describe('Comment model', function () { | ||
16 | it('Should correctly extract mentions', async function () { | ||
17 | const comment = new CommentMock() | ||
18 | |||
19 | comment.text = '@florian @jean@localhost:9000 @flo @another@localhost:9000 @flo2@jean.com hello ' + | ||
20 | 'email@localhost:9000 coucou.com no? @chocobozzz @chocobozzz @end' | ||
21 | const result = comment.extractMentions().sort() | ||
22 | |||
23 | expect(result).to.deep.equal([ 'another', 'chocobozzz', 'end', 'flo', 'florian', 'jean' ]) | ||
24 | }) | ||
25 | }) | ||
diff --git a/server/tests/helpers/core-utils.ts b/server/tests/helpers/core-utils.ts new file mode 100644 index 000000000..e604cf7e3 --- /dev/null +++ b/server/tests/helpers/core-utils.ts | |||
@@ -0,0 +1,98 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { snakeCase, isNumber } from 'lodash' | ||
6 | import { | ||
7 | parseBytes, objectConverter | ||
8 | } from '../../helpers/core-utils' | ||
9 | import { isNumeric } from 'validator' | ||
10 | |||
11 | const expect = chai.expect | ||
12 | |||
13 | describe('Parse Bytes', function () { | ||
14 | |||
15 | it('Should pass when given valid value', async function () { | ||
16 | // just return it | ||
17 | expect(parseBytes(1024)).to.be.eq(1024) | ||
18 | expect(parseBytes(1048576)).to.be.eq(1048576) | ||
19 | expect(parseBytes('1024')).to.be.eq(1024) | ||
20 | expect(parseBytes('1048576')).to.be.eq(1048576) | ||
21 | |||
22 | // sizes | ||
23 | expect(parseBytes('1B')).to.be.eq(1024) | ||
24 | expect(parseBytes('1MB')).to.be.eq(1048576) | ||
25 | expect(parseBytes('1GB')).to.be.eq(1073741824) | ||
26 | expect(parseBytes('1TB')).to.be.eq(1099511627776) | ||
27 | |||
28 | expect(parseBytes('5GB')).to.be.eq(5368709120) | ||
29 | expect(parseBytes('5TB')).to.be.eq(5497558138880) | ||
30 | |||
31 | expect(parseBytes('1024B')).to.be.eq(1048576) | ||
32 | expect(parseBytes('1024MB')).to.be.eq(1073741824) | ||
33 | expect(parseBytes('1024GB')).to.be.eq(1099511627776) | ||
34 | expect(parseBytes('1024TB')).to.be.eq(1125899906842624) | ||
35 | |||
36 | // with whitespace | ||
37 | expect(parseBytes('1 GB')).to.be.eq(1073741824) | ||
38 | expect(parseBytes('1\tGB')).to.be.eq(1073741824) | ||
39 | |||
40 | // sum value | ||
41 | expect(parseBytes('1TB 1024MB')).to.be.eq(1100585369600) | ||
42 | expect(parseBytes('4GB 1024MB')).to.be.eq(5368709120) | ||
43 | expect(parseBytes('4TB 1024GB')).to.be.eq(5497558138880) | ||
44 | expect(parseBytes('4TB 1024GB 0MB')).to.be.eq(5497558138880) | ||
45 | expect(parseBytes('1024TB 1024GB 1024MB')).to.be.eq(1127000492212224) | ||
46 | }) | ||
47 | |||
48 | it('Should be invalid when given invalid value', async function () { | ||
49 | expect(parseBytes('6GB 1GB')).to.be.eq(6) | ||
50 | }) | ||
51 | |||
52 | it('Should convert an object', async function () { | ||
53 | function keyConverter (k: string) { | ||
54 | return snakeCase(k) | ||
55 | } | ||
56 | |||
57 | function valueConverter (v: any) { | ||
58 | if (isNumeric(v + '')) return parseInt('' + v, 10) | ||
59 | |||
60 | return v | ||
61 | } | ||
62 | |||
63 | const obj = { | ||
64 | mySuperKey: 'hello', | ||
65 | mySuper2Key: '45', | ||
66 | mySuper3Key: { | ||
67 | mySuperSubKey: '15', | ||
68 | mySuperSub2Key: 'hello', | ||
69 | mySuperSub3Key: [ '1', 'hello', 2 ], | ||
70 | mySuperSub4Key: 4 | ||
71 | }, | ||
72 | mySuper4Key: 45, | ||
73 | toto: { | ||
74 | super_key: '15', | ||
75 | superKey2: 'hello' | ||
76 | }, | ||
77 | super_key: { | ||
78 | superKey4: 15 | ||
79 | } | ||
80 | } | ||
81 | |||
82 | const res = objectConverter(obj, keyConverter, valueConverter) | ||
83 | |||
84 | expect(res.my_super_key).to.equal('hello') | ||
85 | expect(res.my_super_2_key).to.equal(45) | ||
86 | expect(res.my_super_3_key.my_super_sub_key).to.equal(15) | ||
87 | expect(res.my_super_3_key.my_super_sub_2_key).to.equal('hello') | ||
88 | expect(res.my_super_3_key.my_super_sub_3_key).to.deep.equal([ 1, 'hello', 2 ]) | ||
89 | expect(res.my_super_3_key.my_super_sub_4_key).to.equal(4) | ||
90 | expect(res.toto.super_key).to.equal(15) | ||
91 | expect(res.toto.super_key_2).to.equal('hello') | ||
92 | expect(res.super_key.super_key_4).to.equal(15) | ||
93 | |||
94 | // Immutable | ||
95 | expect(res.mySuperKey).to.be.undefined | ||
96 | expect(obj['my_super_key']).to.be.undefined | ||
97 | }) | ||
98 | }) | ||
diff --git a/server/tests/helpers/index.ts b/server/tests/helpers/index.ts new file mode 100644 index 000000000..551208245 --- /dev/null +++ b/server/tests/helpers/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | import './core-utils' | ||
2 | import './comment-model' | ||
diff --git a/server/tests/index.ts b/server/tests/index.ts index e659fd3df..ed16d65dd 100644 --- a/server/tests/index.ts +++ b/server/tests/index.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | // Order of the tests we want to execute | 1 | // Order of the tests we want to execute |
2 | import './client' | 2 | import './client' |
3 | import './activitypub' | ||
4 | import './feeds/' | 3 | import './feeds/' |
5 | import './cli/' | 4 | import './cli/' |
6 | import './api/' | 5 | import './api/' |
diff --git a/server/tests/misc-endpoints.ts b/server/tests/misc-endpoints.ts index 8fab20971..5f82719da 100644 --- a/server/tests/misc-endpoints.ts +++ b/server/tests/misc-endpoints.ts | |||
@@ -2,7 +2,18 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { flushTests, killallServers, makeGetRequest, runServer, ServerInfo } from './utils' | 5 | import { |
6 | addVideoChannel, | ||
7 | createUser, | ||
8 | flushTests, | ||
9 | killallServers, | ||
10 | makeGetRequest, | ||
11 | runServer, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | uploadVideo | ||
15 | } from '../../shared/utils' | ||
16 | import { VideoPrivacy } from '../../shared/models/videos' | ||
6 | 17 | ||
7 | const expect = chai.expect | 18 | const expect = chai.expect |
8 | 19 | ||
@@ -15,6 +26,7 @@ describe('Test misc endpoints', function () { | |||
15 | await flushTests() | 26 | await flushTests() |
16 | 27 | ||
17 | server = await runServer(1) | 28 | server = await runServer(1) |
29 | await setAccessTokensToServers([ server ]) | ||
18 | }) | 30 | }) |
19 | 31 | ||
20 | describe('Test a well known endpoints', function () { | 32 | describe('Test a well known endpoints', function () { |
@@ -60,6 +72,16 @@ describe('Test misc endpoints', function () { | |||
60 | 72 | ||
61 | expect(res.body.tracking).to.equal('N') | 73 | expect(res.body.tracking).to.equal('N') |
62 | }) | 74 | }) |
75 | |||
76 | it('Should get change-password location', async function () { | ||
77 | const res = await makeGetRequest({ | ||
78 | url: server.url, | ||
79 | path: '/.well-known/change-password', | ||
80 | statusCodeExpected: 302 | ||
81 | }) | ||
82 | |||
83 | expect(res.header.location).to.equal('/my-account/settings') | ||
84 | }) | ||
63 | }) | 85 | }) |
64 | 86 | ||
65 | describe('Test classic static endpoints', function () { | 87 | describe('Test classic static endpoints', function () { |
@@ -93,6 +115,64 @@ describe('Test misc endpoints', function () { | |||
93 | }) | 115 | }) |
94 | }) | 116 | }) |
95 | 117 | ||
118 | describe('Test bots endpoints', function () { | ||
119 | |||
120 | it('Should get the empty sitemap', async function () { | ||
121 | const res = await makeGetRequest({ | ||
122 | url: server.url, | ||
123 | path: '/sitemap.xml', | ||
124 | statusCodeExpected: 200 | ||
125 | }) | ||
126 | |||
127 | expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"') | ||
128 | expect(res.text).to.contain('<url><loc>http://localhost:9001/about/instance</loc></url>') | ||
129 | }) | ||
130 | |||
131 | it('Should get the empty cached sitemap', async function () { | ||
132 | const res = await makeGetRequest({ | ||
133 | url: server.url, | ||
134 | path: '/sitemap.xml', | ||
135 | statusCodeExpected: 200 | ||
136 | }) | ||
137 | |||
138 | expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"') | ||
139 | expect(res.text).to.contain('<url><loc>http://localhost:9001/about/instance</loc></url>') | ||
140 | }) | ||
141 | |||
142 | it('Should add videos, channel and accounts and get sitemap', async function () { | ||
143 | this.timeout(35000) | ||
144 | |||
145 | await uploadVideo(server.url, server.accessToken, { name: 'video 1', nsfw: false }) | ||
146 | await uploadVideo(server.url, server.accessToken, { name: 'video 2', nsfw: false }) | ||
147 | await uploadVideo(server.url, server.accessToken, { name: 'video 3', privacy: VideoPrivacy.PRIVATE }) | ||
148 | |||
149 | await addVideoChannel(server.url, server.accessToken, { name: 'channel1', displayName: 'channel 1' }) | ||
150 | await addVideoChannel(server.url, server.accessToken, { name: 'channel2', displayName: 'channel 2' }) | ||
151 | |||
152 | await createUser(server.url, server.accessToken, 'user1', 'password') | ||
153 | await createUser(server.url, server.accessToken, 'user2', 'password') | ||
154 | |||
155 | const res = await makeGetRequest({ | ||
156 | url: server.url, | ||
157 | path: '/sitemap.xml?t=1', // avoid using cache | ||
158 | statusCodeExpected: 200 | ||
159 | }) | ||
160 | |||
161 | expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"') | ||
162 | expect(res.text).to.contain('<url><loc>http://localhost:9001/about/instance</loc></url>') | ||
163 | |||
164 | expect(res.text).to.contain('<video:title><![CDATA[video 1]]></video:title>') | ||
165 | expect(res.text).to.contain('<video:title><![CDATA[video 2]]></video:title>') | ||
166 | expect(res.text).to.not.contain('<video:title><![CDATA[video 3]]></video:title>') | ||
167 | |||
168 | expect(res.text).to.contain('<url><loc>http://localhost:9001/video-channels/channel1</loc></url>') | ||
169 | expect(res.text).to.contain('<url><loc>http://localhost:9001/video-channels/channel2</loc></url>') | ||
170 | |||
171 | expect(res.text).to.contain('<url><loc>http://localhost:9001/accounts/user1</loc></url>') | ||
172 | expect(res.text).to.contain('<url><loc>http://localhost:9001/accounts/user2</loc></url>') | ||
173 | }) | ||
174 | }) | ||
175 | |||
96 | after(async function () { | 176 | after(async function () { |
97 | killallServers([ server ]) | 177 | killallServers([ server ]) |
98 | }) | 178 | }) |
diff --git a/server/tests/real-world/populate-database.ts b/server/tests/real-world/populate-database.ts index a7fdbd1dc..016503498 100644 --- a/server/tests/real-world/populate-database.ts +++ b/server/tests/real-world/populate-database.ts | |||
@@ -10,7 +10,7 @@ import { | |||
10 | ServerInfo, | 10 | ServerInfo, |
11 | setAccessTokensToServers, | 11 | setAccessTokensToServers, |
12 | uploadVideo | 12 | uploadVideo |
13 | } from '../utils' | 13 | } from '../../../shared/utils' |
14 | import * as Bluebird from 'bluebird' | 14 | import * as Bluebird from 'bluebird' |
15 | 15 | ||
16 | start() | 16 | start() |
diff --git a/server/tests/real-world/real-world.ts b/server/tests/real-world/real-world.ts index a96469b11..ac3baaf9a 100644 --- a/server/tests/real-world/real-world.ts +++ b/server/tests/real-world/real-world.ts | |||
@@ -16,8 +16,8 @@ import { | |||
16 | updateVideo, | 16 | updateVideo, |
17 | uploadVideo, viewVideo, | 17 | uploadVideo, viewVideo, |
18 | wait | 18 | wait |
19 | } from '../utils' | 19 | } from '../../../shared/utils' |
20 | import { getJobsListPaginationAndSort } from '../utils/server/jobs' | 20 | import { getJobsListPaginationAndSort } from '../../../shared/utils/server/jobs' |
21 | 21 | ||
22 | interface ServerInfo extends DefaultServerInfo { | 22 | interface ServerInfo extends DefaultServerInfo { |
23 | requestsNumber: number | 23 | requestsNumber: number |
diff --git a/server/tests/utils/cli/cli.ts b/server/tests/utils/cli/cli.ts deleted file mode 100644 index 54d05e9c6..000000000 --- a/server/tests/utils/cli/cli.ts +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | import { exec } from 'child_process' | ||
2 | |||
3 | import { ServerInfo } from '../server/servers' | ||
4 | |||
5 | function getEnvCli (server?: ServerInfo) { | ||
6 | return `NODE_ENV=test NODE_APP_INSTANCE=${server.serverNumber}` | ||
7 | } | ||
8 | |||
9 | async function execCLI (command: string) { | ||
10 | return new Promise<string>((res, rej) => { | ||
11 | exec(command, (err, stdout, stderr) => { | ||
12 | if (err) return rej(err) | ||
13 | |||
14 | return res(stdout) | ||
15 | }) | ||
16 | }) | ||
17 | } | ||
18 | |||
19 | // --------------------------------------------------------------------------- | ||
20 | |||
21 | export { | ||
22 | execCLI, | ||
23 | getEnvCli | ||
24 | } | ||
diff --git a/server/tests/utils/feeds/feeds.ts b/server/tests/utils/feeds/feeds.ts deleted file mode 100644 index af6df2b20..000000000 --- a/server/tests/utils/feeds/feeds.ts +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | type FeedType = 'videos' | 'video-comments' | ||
4 | |||
5 | function getXMLfeed (url: string, feed: FeedType, format?: string) { | ||
6 | const path = '/feeds/' + feed + '.xml' | ||
7 | |||
8 | return request(url) | ||
9 | .get(path) | ||
10 | .query((format) ? { format: format } : {}) | ||
11 | .set('Accept', 'application/xml') | ||
12 | .expect(200) | ||
13 | .expect('Content-Type', /xml/) | ||
14 | } | ||
15 | |||
16 | function getJSONfeed (url: string, feed: FeedType, query: any = {}) { | ||
17 | const path = '/feeds/' + feed + '.json' | ||
18 | |||
19 | return request(url) | ||
20 | .get(path) | ||
21 | .query(query) | ||
22 | .set('Accept', 'application/json') | ||
23 | .expect(200) | ||
24 | .expect('Content-Type', /json/) | ||
25 | } | ||
26 | |||
27 | // --------------------------------------------------------------------------- | ||
28 | |||
29 | export { | ||
30 | getXMLfeed, | ||
31 | getJSONfeed | ||
32 | } | ||
diff --git a/server/tests/utils/index.ts b/server/tests/utils/index.ts deleted file mode 100644 index 897389824..000000000 --- a/server/tests/utils/index.ts +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | export * from './server/activitypub' | ||
2 | export * from './cli/cli' | ||
3 | export * from './server/clients' | ||
4 | export * from './server/config' | ||
5 | export * from './users/login' | ||
6 | export * from './miscs/miscs' | ||
7 | export * from './server/follows' | ||
8 | export * from './requests/requests' | ||
9 | export * from './server/servers' | ||
10 | export * from './videos/services' | ||
11 | export * from './users/users' | ||
12 | export * from './videos/video-abuses' | ||
13 | export * from './videos/video-blacklist' | ||
14 | export * from './videos/video-channels' | ||
15 | export * from './videos/videos' | ||
16 | export * from './videos/video-change-ownership' | ||
17 | export * from './feeds/feeds' | ||
18 | export * from './search/videos' | ||
diff --git a/server/tests/utils/miscs/email.ts b/server/tests/utils/miscs/email.ts deleted file mode 100644 index 21accd09d..000000000 --- a/server/tests/utils/miscs/email.ts +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | import * as MailDev from 'maildev' | ||
2 | |||
3 | function mockSmtpServer (emailsCollection: object[]) { | ||
4 | const maildev = new MailDev({ | ||
5 | ip: '127.0.0.1', | ||
6 | smtp: 1025, | ||
7 | disableWeb: true, | ||
8 | silent: true | ||
9 | }) | ||
10 | maildev.on('new', email => emailsCollection.push(email)) | ||
11 | |||
12 | return new Promise((res, rej) => { | ||
13 | maildev.listen(err => { | ||
14 | if (err) return rej(err) | ||
15 | |||
16 | return res() | ||
17 | }) | ||
18 | }) | ||
19 | } | ||
20 | |||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | export { | ||
24 | mockSmtpServer | ||
25 | } | ||
diff --git a/server/tests/utils/miscs/miscs.ts b/server/tests/utils/miscs/miscs.ts deleted file mode 100644 index b2f80e9b1..000000000 --- a/server/tests/utils/miscs/miscs.ts +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import { isAbsolute, join } from 'path' | ||
5 | import * as request from 'supertest' | ||
6 | import * as WebTorrent from 'webtorrent' | ||
7 | import { readFile } from 'fs-extra' | ||
8 | |||
9 | const expect = chai.expect | ||
10 | let webtorrent = new WebTorrent() | ||
11 | |||
12 | function immutableAssign <T, U> (target: T, source: U) { | ||
13 | return Object.assign<{}, T, U>({}, target, source) | ||
14 | } | ||
15 | |||
16 | // Default interval -> 5 minutes | ||
17 | function dateIsValid (dateString: string, interval = 300000) { | ||
18 | const dateToCheck = new Date(dateString) | ||
19 | const now = new Date() | ||
20 | |||
21 | return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval | ||
22 | } | ||
23 | |||
24 | function wait (milliseconds: number) { | ||
25 | return new Promise(resolve => setTimeout(resolve, milliseconds)) | ||
26 | } | ||
27 | |||
28 | function webtorrentAdd (torrent: string, refreshWebTorrent = false) { | ||
29 | if (refreshWebTorrent === true) webtorrent = new WebTorrent() | ||
30 | |||
31 | return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res)) | ||
32 | } | ||
33 | |||
34 | function root () { | ||
35 | // We are in server/tests/utils/miscs | ||
36 | return join(__dirname, '..', '..', '..', '..') | ||
37 | } | ||
38 | |||
39 | async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') { | ||
40 | const res = await request(url) | ||
41 | .get(imagePath) | ||
42 | .expect(200) | ||
43 | |||
44 | const body = res.body | ||
45 | |||
46 | const data = await readFile(join(__dirname, '..', '..', 'fixtures', imageName + extension)) | ||
47 | const minLength = body.length - ((20 * body.length) / 100) | ||
48 | const maxLength = body.length + ((20 * body.length) / 100) | ||
49 | |||
50 | expect(data.length).to.be.above(minLength) | ||
51 | expect(data.length).to.be.below(maxLength) | ||
52 | } | ||
53 | |||
54 | function buildAbsoluteFixturePath (path: string) { | ||
55 | if (isAbsolute(path)) { | ||
56 | return path | ||
57 | } | ||
58 | |||
59 | return join(__dirname, '..', '..', 'fixtures', path) | ||
60 | } | ||
61 | |||
62 | // --------------------------------------------------------------------------- | ||
63 | |||
64 | export { | ||
65 | dateIsValid, | ||
66 | wait, | ||
67 | webtorrentAdd, | ||
68 | immutableAssign, | ||
69 | testImage, | ||
70 | buildAbsoluteFixturePath, | ||
71 | root | ||
72 | } | ||
diff --git a/server/tests/utils/overviews/overviews.ts b/server/tests/utils/overviews/overviews.ts deleted file mode 100644 index 23e3ceb1e..000000000 --- a/server/tests/utils/overviews/overviews.ts +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | import { makeGetRequest } from '../requests/requests' | ||
2 | |||
3 | function getVideosOverview (url: string, useCache = false) { | ||
4 | const path = '/api/v1/overviews/videos' | ||
5 | |||
6 | const query = { | ||
7 | t: useCache ? undefined : new Date().getTime() | ||
8 | } | ||
9 | |||
10 | return makeGetRequest({ | ||
11 | url, | ||
12 | path, | ||
13 | query, | ||
14 | statusCodeExpected: 200 | ||
15 | }) | ||
16 | } | ||
17 | |||
18 | export { getVideosOverview } | ||
diff --git a/server/tests/utils/requests/check-api-params.ts b/server/tests/utils/requests/check-api-params.ts deleted file mode 100644 index edb47e0e9..000000000 --- a/server/tests/utils/requests/check-api-params.ts +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | import { makeGetRequest } from './requests' | ||
2 | import { immutableAssign } from '..' | ||
3 | |||
4 | function checkBadStartPagination (url: string, path: string, token?: string, query = {}) { | ||
5 | return makeGetRequest({ | ||
6 | url, | ||
7 | path, | ||
8 | token, | ||
9 | query: immutableAssign(query, { start: 'hello' }), | ||
10 | statusCodeExpected: 400 | ||
11 | }) | ||
12 | } | ||
13 | |||
14 | function checkBadCountPagination (url: string, path: string, token?: string, query = {}) { | ||
15 | return makeGetRequest({ | ||
16 | url, | ||
17 | path, | ||
18 | token, | ||
19 | query: immutableAssign(query, { count: 'hello' }), | ||
20 | statusCodeExpected: 400 | ||
21 | }) | ||
22 | } | ||
23 | |||
24 | function checkBadSortPagination (url: string, path: string, token?: string, query = {}) { | ||
25 | return makeGetRequest({ | ||
26 | url, | ||
27 | path, | ||
28 | token, | ||
29 | query: immutableAssign(query, { sort: 'hello' }), | ||
30 | statusCodeExpected: 400 | ||
31 | }) | ||
32 | } | ||
33 | |||
34 | // --------------------------------------------------------------------------- | ||
35 | |||
36 | export { | ||
37 | checkBadStartPagination, | ||
38 | checkBadCountPagination, | ||
39 | checkBadSortPagination | ||
40 | } | ||
diff --git a/server/tests/utils/requests/requests.ts b/server/tests/utils/requests/requests.ts deleted file mode 100644 index 27a529eda..000000000 --- a/server/tests/utils/requests/requests.ts +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { buildAbsoluteFixturePath } from '../miscs/miscs' | ||
3 | import { isAbsolute, join } from 'path' | ||
4 | |||
5 | function makeGetRequest (options: { | ||
6 | url: string, | ||
7 | path: string, | ||
8 | query?: any, | ||
9 | token?: string, | ||
10 | statusCodeExpected?: number, | ||
11 | contentType?: string | ||
12 | }) { | ||
13 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | ||
14 | if (options.contentType === undefined) options.contentType = 'application/json' | ||
15 | |||
16 | const req = request(options.url) | ||
17 | .get(options.path) | ||
18 | |||
19 | if (options.contentType) req.set('Accept', options.contentType) | ||
20 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
21 | if (options.query) req.query(options.query) | ||
22 | |||
23 | return req.expect(options.statusCodeExpected) | ||
24 | } | ||
25 | |||
26 | function makeDeleteRequest (options: { | ||
27 | url: string, | ||
28 | path: string, | ||
29 | token?: string, | ||
30 | statusCodeExpected?: number | ||
31 | }) { | ||
32 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | ||
33 | |||
34 | const req = request(options.url) | ||
35 | .delete(options.path) | ||
36 | .set('Accept', 'application/json') | ||
37 | |||
38 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
39 | |||
40 | return req | ||
41 | .expect('Content-Type', /json/) | ||
42 | .expect(options.statusCodeExpected) | ||
43 | } | ||
44 | |||
45 | function makeUploadRequest (options: { | ||
46 | url: string, | ||
47 | method?: 'POST' | 'PUT', | ||
48 | path: string, | ||
49 | token?: string, | ||
50 | fields: { [ fieldName: string ]: any }, | ||
51 | attaches: { [ attachName: string ]: any | any[] }, | ||
52 | statusCodeExpected?: number | ||
53 | }) { | ||
54 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | ||
55 | |||
56 | let req: request.Test | ||
57 | if (options.method === 'PUT') { | ||
58 | req = request(options.url).put(options.path) | ||
59 | } else { | ||
60 | req = request(options.url).post(options.path) | ||
61 | } | ||
62 | |||
63 | req.set('Accept', 'application/json') | ||
64 | |||
65 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
66 | |||
67 | Object.keys(options.fields).forEach(field => { | ||
68 | const value = options.fields[field] | ||
69 | |||
70 | if (Array.isArray(value)) { | ||
71 | for (let i = 0; i < value.length; i++) { | ||
72 | req.field(field + '[' + i + ']', value[i]) | ||
73 | } | ||
74 | } else { | ||
75 | req.field(field, value) | ||
76 | } | ||
77 | }) | ||
78 | |||
79 | Object.keys(options.attaches).forEach(attach => { | ||
80 | const value = options.attaches[attach] | ||
81 | if (Array.isArray(value)) { | ||
82 | req.attach(attach, buildAbsoluteFixturePath(value[0]), value[1]) | ||
83 | } else { | ||
84 | req.attach(attach, buildAbsoluteFixturePath(value)) | ||
85 | } | ||
86 | }) | ||
87 | |||
88 | return req.expect(options.statusCodeExpected) | ||
89 | } | ||
90 | |||
91 | function makePostBodyRequest (options: { | ||
92 | url: string, | ||
93 | path: string, | ||
94 | token?: string, | ||
95 | fields?: { [ fieldName: string ]: any }, | ||
96 | statusCodeExpected?: number | ||
97 | }) { | ||
98 | if (!options.fields) options.fields = {} | ||
99 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | ||
100 | |||
101 | const req = request(options.url) | ||
102 | .post(options.path) | ||
103 | .set('Accept', 'application/json') | ||
104 | |||
105 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
106 | |||
107 | return req.send(options.fields) | ||
108 | .expect(options.statusCodeExpected) | ||
109 | } | ||
110 | |||
111 | function makePutBodyRequest (options: { | ||
112 | url: string, | ||
113 | path: string, | ||
114 | token?: string, | ||
115 | fields: { [ fieldName: string ]: any }, | ||
116 | statusCodeExpected?: number | ||
117 | }) { | ||
118 | if (!options.statusCodeExpected) options.statusCodeExpected = 400 | ||
119 | |||
120 | const req = request(options.url) | ||
121 | .put(options.path) | ||
122 | .set('Accept', 'application/json') | ||
123 | |||
124 | if (options.token) req.set('Authorization', 'Bearer ' + options.token) | ||
125 | |||
126 | return req.send(options.fields) | ||
127 | .expect(options.statusCodeExpected) | ||
128 | } | ||
129 | |||
130 | function makeHTMLRequest (url: string, path: string) { | ||
131 | return request(url) | ||
132 | .get(path) | ||
133 | .set('Accept', 'text/html') | ||
134 | .expect(200) | ||
135 | } | ||
136 | |||
137 | function updateAvatarRequest (options: { | ||
138 | url: string, | ||
139 | path: string, | ||
140 | accessToken: string, | ||
141 | fixture: string | ||
142 | }) { | ||
143 | let filePath = '' | ||
144 | if (isAbsolute(options.fixture)) { | ||
145 | filePath = options.fixture | ||
146 | } else { | ||
147 | filePath = join(__dirname, '..', '..', 'fixtures', options.fixture) | ||
148 | } | ||
149 | |||
150 | return makeUploadRequest({ | ||
151 | url: options.url, | ||
152 | path: options.path, | ||
153 | token: options.accessToken, | ||
154 | fields: {}, | ||
155 | attaches: { avatarfile: filePath }, | ||
156 | statusCodeExpected: 200 | ||
157 | }) | ||
158 | } | ||
159 | |||
160 | // --------------------------------------------------------------------------- | ||
161 | |||
162 | export { | ||
163 | makeHTMLRequest, | ||
164 | makeGetRequest, | ||
165 | makeUploadRequest, | ||
166 | makePostBodyRequest, | ||
167 | makePutBodyRequest, | ||
168 | makeDeleteRequest, | ||
169 | updateAvatarRequest | ||
170 | } | ||
diff --git a/server/tests/utils/search/video-channels.ts b/server/tests/utils/search/video-channels.ts deleted file mode 100644 index 0532134ae..000000000 --- a/server/tests/utils/search/video-channels.ts +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | import { makeGetRequest } from '../requests/requests' | ||
2 | |||
3 | function searchVideoChannel (url: string, search: string, token?: string, statusCodeExpected = 200) { | ||
4 | const path = '/api/v1/search/video-channels' | ||
5 | |||
6 | return makeGetRequest({ | ||
7 | url, | ||
8 | path, | ||
9 | query: { | ||
10 | sort: '-createdAt', | ||
11 | search | ||
12 | }, | ||
13 | token, | ||
14 | statusCodeExpected | ||
15 | }) | ||
16 | } | ||
17 | |||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | export { | ||
21 | searchVideoChannel | ||
22 | } | ||
diff --git a/server/tests/utils/search/videos.ts b/server/tests/utils/search/videos.ts deleted file mode 100644 index 3a0c10e42..000000000 --- a/server/tests/utils/search/videos.ts +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as request from 'supertest' | ||
4 | import { VideosSearchQuery } from '../../../../shared/models/search' | ||
5 | import { immutableAssign } from '..' | ||
6 | |||
7 | function searchVideo (url: string, search: string) { | ||
8 | const path = '/api/v1/search/videos' | ||
9 | const req = request(url) | ||
10 | .get(path) | ||
11 | .query({ sort: '-publishedAt', search }) | ||
12 | .set('Accept', 'application/json') | ||
13 | |||
14 | return req.expect(200) | ||
15 | .expect('Content-Type', /json/) | ||
16 | } | ||
17 | |||
18 | function searchVideoWithToken (url: string, search: string, token: string, query: { nsfw?: boolean } = {}) { | ||
19 | const path = '/api/v1/search/videos' | ||
20 | const req = request(url) | ||
21 | .get(path) | ||
22 | .set('Authorization', 'Bearer ' + token) | ||
23 | .query(immutableAssign(query, { sort: '-publishedAt', search })) | ||
24 | .set('Accept', 'application/json') | ||
25 | |||
26 | return req.expect(200) | ||
27 | .expect('Content-Type', /json/) | ||
28 | } | ||
29 | |||
30 | function searchVideoWithPagination (url: string, search: string, start: number, count: number, sort?: string) { | ||
31 | const path = '/api/v1/search/videos' | ||
32 | |||
33 | const req = request(url) | ||
34 | .get(path) | ||
35 | .query({ start }) | ||
36 | .query({ search }) | ||
37 | .query({ count }) | ||
38 | |||
39 | if (sort) req.query({ sort }) | ||
40 | |||
41 | return req.set('Accept', 'application/json') | ||
42 | .expect(200) | ||
43 | .expect('Content-Type', /json/) | ||
44 | } | ||
45 | |||
46 | function searchVideoWithSort (url: string, search: string, sort: string) { | ||
47 | const path = '/api/v1/search/videos' | ||
48 | |||
49 | return request(url) | ||
50 | .get(path) | ||
51 | .query({ search }) | ||
52 | .query({ sort }) | ||
53 | .set('Accept', 'application/json') | ||
54 | .expect(200) | ||
55 | .expect('Content-Type', /json/) | ||
56 | } | ||
57 | |||
58 | function advancedVideosSearch (url: string, options: VideosSearchQuery) { | ||
59 | const path = '/api/v1/search/videos' | ||
60 | |||
61 | return request(url) | ||
62 | .get(path) | ||
63 | .query(options) | ||
64 | .set('Accept', 'application/json') | ||
65 | .expect(200) | ||
66 | .expect('Content-Type', /json/) | ||
67 | } | ||
68 | |||
69 | // --------------------------------------------------------------------------- | ||
70 | |||
71 | export { | ||
72 | searchVideo, | ||
73 | advancedVideosSearch, | ||
74 | searchVideoWithToken, | ||
75 | searchVideoWithPagination, | ||
76 | searchVideoWithSort | ||
77 | } | ||
diff --git a/server/tests/utils/server/activitypub.ts b/server/tests/utils/server/activitypub.ts deleted file mode 100644 index cf3c1c3b3..000000000 --- a/server/tests/utils/server/activitypub.ts +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | function makeActivityPubGetRequest (url: string, path: string) { | ||
4 | return request(url) | ||
5 | .get(path) | ||
6 | .set('Accept', 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8') | ||
7 | .expect(200) | ||
8 | .expect('Content-Type', /json/) | ||
9 | } | ||
10 | |||
11 | // --------------------------------------------------------------------------- | ||
12 | |||
13 | export { | ||
14 | makeActivityPubGetRequest | ||
15 | } | ||
diff --git a/server/tests/utils/server/clients.ts b/server/tests/utils/server/clients.ts deleted file mode 100644 index 273aac747..000000000 --- a/server/tests/utils/server/clients.ts +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import * as urlUtil from 'url' | ||
3 | |||
4 | function getClient (url: string) { | ||
5 | const path = '/api/v1/oauth-clients/local' | ||
6 | |||
7 | return request(url) | ||
8 | .get(path) | ||
9 | .set('Host', urlUtil.parse(url).host) | ||
10 | .set('Accept', 'application/json') | ||
11 | .expect(200) | ||
12 | .expect('Content-Type', /json/) | ||
13 | } | ||
14 | |||
15 | // --------------------------------------------------------------------------- | ||
16 | |||
17 | export { | ||
18 | getClient | ||
19 | } | ||
diff --git a/server/tests/utils/server/config.ts b/server/tests/utils/server/config.ts deleted file mode 100644 index b85e02ab7..000000000 --- a/server/tests/utils/server/config.ts +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../' | ||
2 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' | ||
3 | |||
4 | function getConfig (url: string) { | ||
5 | const path = '/api/v1/config' | ||
6 | |||
7 | return makeGetRequest({ | ||
8 | url, | ||
9 | path, | ||
10 | statusCodeExpected: 200 | ||
11 | }) | ||
12 | } | ||
13 | |||
14 | function getAbout (url: string) { | ||
15 | const path = '/api/v1/config/about' | ||
16 | |||
17 | return makeGetRequest({ | ||
18 | url, | ||
19 | path, | ||
20 | statusCodeExpected: 200 | ||
21 | }) | ||
22 | } | ||
23 | |||
24 | function getCustomConfig (url: string, token: string, statusCodeExpected = 200) { | ||
25 | const path = '/api/v1/config/custom' | ||
26 | |||
27 | return makeGetRequest({ | ||
28 | url, | ||
29 | token, | ||
30 | path, | ||
31 | statusCodeExpected | ||
32 | }) | ||
33 | } | ||
34 | |||
35 | function updateCustomConfig (url: string, token: string, newCustomConfig: CustomConfig, statusCodeExpected = 200) { | ||
36 | const path = '/api/v1/config/custom' | ||
37 | |||
38 | return makePutBodyRequest({ | ||
39 | url, | ||
40 | token, | ||
41 | path, | ||
42 | fields: newCustomConfig, | ||
43 | statusCodeExpected | ||
44 | }) | ||
45 | } | ||
46 | |||
47 | function updateCustomSubConfig (url: string, token: string, newConfig: any) { | ||
48 | const updateParams: CustomConfig = { | ||
49 | instance: { | ||
50 | name: 'PeerTube updated', | ||
51 | shortDescription: 'my short description', | ||
52 | description: 'my super description', | ||
53 | terms: 'my super terms', | ||
54 | defaultClientRoute: '/videos/recently-added', | ||
55 | defaultNSFWPolicy: 'blur', | ||
56 | customizations: { | ||
57 | javascript: 'alert("coucou")', | ||
58 | css: 'body { background-color: red; }' | ||
59 | } | ||
60 | }, | ||
61 | services: { | ||
62 | twitter: { | ||
63 | username: '@MySuperUsername', | ||
64 | whitelisted: true | ||
65 | } | ||
66 | }, | ||
67 | cache: { | ||
68 | previews: { | ||
69 | size: 2 | ||
70 | }, | ||
71 | captions: { | ||
72 | size: 3 | ||
73 | } | ||
74 | }, | ||
75 | signup: { | ||
76 | enabled: false, | ||
77 | limit: 5, | ||
78 | requiresEmailVerification: false | ||
79 | }, | ||
80 | admin: { | ||
81 | email: 'superadmin1@example.com' | ||
82 | }, | ||
83 | user: { | ||
84 | videoQuota: 5242881, | ||
85 | videoQuotaDaily: 318742 | ||
86 | }, | ||
87 | transcoding: { | ||
88 | enabled: true, | ||
89 | threads: 1, | ||
90 | resolutions: { | ||
91 | '240p': false, | ||
92 | '360p': true, | ||
93 | '480p': true, | ||
94 | '720p': false, | ||
95 | '1080p': false | ||
96 | } | ||
97 | }, | ||
98 | import: { | ||
99 | videos: { | ||
100 | http: { | ||
101 | enabled: false | ||
102 | }, | ||
103 | torrent: { | ||
104 | enabled: false | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | Object.assign(updateParams, newConfig) | ||
111 | |||
112 | return updateCustomConfig(url, token, updateParams) | ||
113 | } | ||
114 | |||
115 | function deleteCustomConfig (url: string, token: string, statusCodeExpected = 200) { | ||
116 | const path = '/api/v1/config/custom' | ||
117 | |||
118 | return makeDeleteRequest({ | ||
119 | url, | ||
120 | token, | ||
121 | path, | ||
122 | statusCodeExpected | ||
123 | }) | ||
124 | } | ||
125 | |||
126 | // --------------------------------------------------------------------------- | ||
127 | |||
128 | export { | ||
129 | getConfig, | ||
130 | getCustomConfig, | ||
131 | updateCustomConfig, | ||
132 | getAbout, | ||
133 | deleteCustomConfig, | ||
134 | updateCustomSubConfig | ||
135 | } | ||
diff --git a/server/tests/utils/server/follows.ts b/server/tests/utils/server/follows.ts deleted file mode 100644 index 8a65a958b..000000000 --- a/server/tests/utils/server/follows.ts +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { ServerInfo } from './servers' | ||
3 | import { waitJobs } from './jobs' | ||
4 | |||
5 | function getFollowersListPaginationAndSort (url: string, start: number, count: number, sort: string) { | ||
6 | const path = '/api/v1/server/followers' | ||
7 | |||
8 | return request(url) | ||
9 | .get(path) | ||
10 | .query({ start }) | ||
11 | .query({ count }) | ||
12 | .query({ sort }) | ||
13 | .set('Accept', 'application/json') | ||
14 | .expect(200) | ||
15 | .expect('Content-Type', /json/) | ||
16 | } | ||
17 | |||
18 | function getFollowingListPaginationAndSort (url: string, start: number, count: number, sort: string) { | ||
19 | const path = '/api/v1/server/following' | ||
20 | |||
21 | return request(url) | ||
22 | .get(path) | ||
23 | .query({ start }) | ||
24 | .query({ count }) | ||
25 | .query({ sort }) | ||
26 | .set('Accept', 'application/json') | ||
27 | .expect(200) | ||
28 | .expect('Content-Type', /json/) | ||
29 | } | ||
30 | |||
31 | async function follow (follower: string, following: string[], accessToken: string, expectedStatus = 204) { | ||
32 | const path = '/api/v1/server/following' | ||
33 | |||
34 | const followingHosts = following.map(f => f.replace(/^http:\/\//, '')) | ||
35 | const res = await request(follower) | ||
36 | .post(path) | ||
37 | .set('Accept', 'application/json') | ||
38 | .set('Authorization', 'Bearer ' + accessToken) | ||
39 | .send({ 'hosts': followingHosts }) | ||
40 | .expect(expectedStatus) | ||
41 | |||
42 | return res | ||
43 | } | ||
44 | |||
45 | async function unfollow (url: string, accessToken: string, target: ServerInfo, expectedStatus = 204) { | ||
46 | const path = '/api/v1/server/following/' + target.host | ||
47 | |||
48 | const res = await request(url) | ||
49 | .delete(path) | ||
50 | .set('Accept', 'application/json') | ||
51 | .set('Authorization', 'Bearer ' + accessToken) | ||
52 | .expect(expectedStatus) | ||
53 | |||
54 | return res | ||
55 | } | ||
56 | |||
57 | async function doubleFollow (server1: ServerInfo, server2: ServerInfo) { | ||
58 | await Promise.all([ | ||
59 | follow(server1.url, [ server2.url ], server1.accessToken), | ||
60 | follow(server2.url, [ server1.url ], server2.accessToken) | ||
61 | ]) | ||
62 | |||
63 | // Wait request propagation | ||
64 | await waitJobs([ server1, server2 ]) | ||
65 | |||
66 | return true | ||
67 | } | ||
68 | |||
69 | // --------------------------------------------------------------------------- | ||
70 | |||
71 | export { | ||
72 | getFollowersListPaginationAndSort, | ||
73 | getFollowingListPaginationAndSort, | ||
74 | unfollow, | ||
75 | follow, | ||
76 | doubleFollow | ||
77 | } | ||
diff --git a/server/tests/utils/server/jobs.ts b/server/tests/utils/server/jobs.ts deleted file mode 100644 index 4c02cace5..000000000 --- a/server/tests/utils/server/jobs.ts +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { Job, JobState } from '../../../../shared/models' | ||
3 | import { ServerInfo, wait } from '../index' | ||
4 | |||
5 | function getJobsList (url: string, accessToken: string, state: JobState) { | ||
6 | const path = '/api/v1/jobs/' + state | ||
7 | |||
8 | return request(url) | ||
9 | .get(path) | ||
10 | .set('Accept', 'application/json') | ||
11 | .set('Authorization', 'Bearer ' + accessToken) | ||
12 | .expect(200) | ||
13 | .expect('Content-Type', /json/) | ||
14 | } | ||
15 | |||
16 | function getJobsListPaginationAndSort (url: string, accessToken: string, state: JobState, start: number, count: number, sort: string) { | ||
17 | const path = '/api/v1/jobs/' + state | ||
18 | |||
19 | return request(url) | ||
20 | .get(path) | ||
21 | .query({ start }) | ||
22 | .query({ count }) | ||
23 | .query({ sort }) | ||
24 | .set('Accept', 'application/json') | ||
25 | .set('Authorization', 'Bearer ' + accessToken) | ||
26 | .expect(200) | ||
27 | .expect('Content-Type', /json/) | ||
28 | } | ||
29 | |||
30 | async function waitJobs (serversArg: ServerInfo[] | ServerInfo) { | ||
31 | let servers: ServerInfo[] | ||
32 | |||
33 | if (Array.isArray(serversArg) === false) servers = [ serversArg as ServerInfo ] | ||
34 | else servers = serversArg as ServerInfo[] | ||
35 | |||
36 | const states: JobState[] = [ 'waiting', 'active', 'delayed' ] | ||
37 | const tasks: Promise<any>[] = [] | ||
38 | let pendingRequests: boolean | ||
39 | |||
40 | do { | ||
41 | pendingRequests = false | ||
42 | |||
43 | // Check if each server has pending request | ||
44 | for (const server of servers) { | ||
45 | for (const state of states) { | ||
46 | const p = getJobsListPaginationAndSort(server.url, server.accessToken, state, 0, 10, '-createdAt') | ||
47 | .then(res => res.body.data) | ||
48 | .then((jobs: Job[]) => jobs.filter(j => j.type !== 'videos-views')) | ||
49 | .then(jobs => { | ||
50 | if (jobs.length !== 0) pendingRequests = true | ||
51 | }) | ||
52 | tasks.push(p) | ||
53 | } | ||
54 | } | ||
55 | |||
56 | await Promise.all(tasks) | ||
57 | |||
58 | // Retry, in case of new jobs were created | ||
59 | if (pendingRequests === false) { | ||
60 | await wait(1000) | ||
61 | |||
62 | await Promise.all(tasks) | ||
63 | } | ||
64 | |||
65 | if (pendingRequests) { | ||
66 | await wait(1000) | ||
67 | } | ||
68 | } while (pendingRequests) | ||
69 | } | ||
70 | |||
71 | // --------------------------------------------------------------------------- | ||
72 | |||
73 | export { | ||
74 | getJobsList, | ||
75 | waitJobs, | ||
76 | getJobsListPaginationAndSort | ||
77 | } | ||
diff --git a/server/tests/utils/server/redundancy.ts b/server/tests/utils/server/redundancy.ts deleted file mode 100644 index c39ff2c8b..000000000 --- a/server/tests/utils/server/redundancy.ts +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | import { makePutBodyRequest } from '../requests/requests' | ||
2 | |||
3 | async function updateRedundancy (url: string, accessToken: string, host: string, redundancyAllowed: boolean, expectedStatus = 204) { | ||
4 | const path = '/api/v1/server/redundancy/' + host | ||
5 | |||
6 | return makePutBodyRequest({ | ||
7 | url, | ||
8 | path, | ||
9 | token: accessToken, | ||
10 | fields: { redundancyAllowed }, | ||
11 | statusCodeExpected: expectedStatus | ||
12 | }) | ||
13 | } | ||
14 | |||
15 | export { | ||
16 | updateRedundancy | ||
17 | } | ||
diff --git a/server/tests/utils/server/servers.ts b/server/tests/utils/server/servers.ts deleted file mode 100644 index 3c946db27..000000000 --- a/server/tests/utils/server/servers.ts +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | import { ChildProcess, exec, fork } from 'child_process' | ||
2 | import { join } from 'path' | ||
3 | import { root, wait } from '../miscs/miscs' | ||
4 | import { readFile } from 'fs-extra' | ||
5 | |||
6 | interface ServerInfo { | ||
7 | app: ChildProcess, | ||
8 | url: string | ||
9 | host: string | ||
10 | serverNumber: number | ||
11 | |||
12 | client: { | ||
13 | id: string, | ||
14 | secret: string | ||
15 | } | ||
16 | |||
17 | user: { | ||
18 | username: string, | ||
19 | password: string, | ||
20 | email?: string | ||
21 | } | ||
22 | |||
23 | accessToken?: string | ||
24 | |||
25 | video?: { | ||
26 | id: number | ||
27 | uuid: string | ||
28 | name: string | ||
29 | account: { | ||
30 | name: string | ||
31 | } | ||
32 | } | ||
33 | |||
34 | remoteVideo?: { | ||
35 | id: number | ||
36 | uuid: string | ||
37 | } | ||
38 | } | ||
39 | |||
40 | function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) { | ||
41 | let apps = [] | ||
42 | let i = 0 | ||
43 | |||
44 | return new Promise<ServerInfo[]>(res => { | ||
45 | function anotherServerDone (serverNumber, app) { | ||
46 | apps[serverNumber - 1] = app | ||
47 | i++ | ||
48 | if (i === totalServers) { | ||
49 | return res(apps) | ||
50 | } | ||
51 | } | ||
52 | |||
53 | flushTests() | ||
54 | .then(() => { | ||
55 | for (let j = 1; j <= totalServers; j++) { | ||
56 | runServer(j, configOverride).then(app => anotherServerDone(j, app)) | ||
57 | } | ||
58 | }) | ||
59 | }) | ||
60 | } | ||
61 | |||
62 | function flushTests () { | ||
63 | return new Promise<void>((res, rej) => { | ||
64 | return exec('npm run clean:server:test', err => { | ||
65 | if (err) return rej(err) | ||
66 | |||
67 | return res() | ||
68 | }) | ||
69 | }) | ||
70 | } | ||
71 | |||
72 | function runServer (serverNumber: number, configOverride?: Object) { | ||
73 | const server: ServerInfo = { | ||
74 | app: null, | ||
75 | serverNumber: serverNumber, | ||
76 | url: `http://localhost:${9000 + serverNumber}`, | ||
77 | host: `localhost:${9000 + serverNumber}`, | ||
78 | client: { | ||
79 | id: null, | ||
80 | secret: null | ||
81 | }, | ||
82 | user: { | ||
83 | username: null, | ||
84 | password: null | ||
85 | } | ||
86 | } | ||
87 | |||
88 | // These actions are async so we need to be sure that they have both been done | ||
89 | const serverRunString = { | ||
90 | 'Server listening': false | ||
91 | } | ||
92 | const key = 'Database peertube_test' + serverNumber + ' is ready' | ||
93 | serverRunString[key] = false | ||
94 | |||
95 | const regexps = { | ||
96 | client_id: 'Client id: (.+)', | ||
97 | client_secret: 'Client secret: (.+)', | ||
98 | user_username: 'Username: (.+)', | ||
99 | user_password: 'User password: (.+)' | ||
100 | } | ||
101 | |||
102 | // Share the environment | ||
103 | const env = Object.create(process.env) | ||
104 | env['NODE_ENV'] = 'test' | ||
105 | env['NODE_APP_INSTANCE'] = serverNumber.toString() | ||
106 | |||
107 | if (configOverride !== undefined) { | ||
108 | env['NODE_CONFIG'] = JSON.stringify(configOverride) | ||
109 | } | ||
110 | |||
111 | const options = { | ||
112 | silent: true, | ||
113 | env: env, | ||
114 | detached: true | ||
115 | } | ||
116 | |||
117 | return new Promise<ServerInfo>(res => { | ||
118 | server.app = fork(join(__dirname, '..', '..', '..', '..', 'dist', 'server.js'), [], options) | ||
119 | server.app.stdout.on('data', function onStdout (data) { | ||
120 | let dontContinue = false | ||
121 | |||
122 | // Capture things if we want to | ||
123 | for (const key of Object.keys(regexps)) { | ||
124 | const regexp = regexps[key] | ||
125 | const matches = data.toString().match(regexp) | ||
126 | if (matches !== null) { | ||
127 | if (key === 'client_id') server.client.id = matches[1] | ||
128 | else if (key === 'client_secret') server.client.secret = matches[1] | ||
129 | else if (key === 'user_username') server.user.username = matches[1] | ||
130 | else if (key === 'user_password') server.user.password = matches[1] | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // Check if all required sentences are here | ||
135 | for (const key of Object.keys(serverRunString)) { | ||
136 | if (data.toString().indexOf(key) !== -1) serverRunString[key] = true | ||
137 | if (serverRunString[key] === false) dontContinue = true | ||
138 | } | ||
139 | |||
140 | // If no, there is maybe one thing not already initialized (client/user credentials generation...) | ||
141 | if (dontContinue === true) return | ||
142 | |||
143 | server.app.stdout.removeListener('data', onStdout) | ||
144 | res(server) | ||
145 | }) | ||
146 | }) | ||
147 | } | ||
148 | |||
149 | async function reRunServer (server: ServerInfo, configOverride?: any) { | ||
150 | const newServer = await runServer(server.serverNumber, configOverride) | ||
151 | server.app = newServer.app | ||
152 | |||
153 | return server | ||
154 | } | ||
155 | |||
156 | function killallServers (servers: ServerInfo[]) { | ||
157 | for (const server of servers) { | ||
158 | process.kill(-server.app.pid) | ||
159 | } | ||
160 | } | ||
161 | |||
162 | async function waitUntilLog (server: ServerInfo, str: string, count = 1) { | ||
163 | const logfile = join(root(), 'test' + server.serverNumber, 'logs/peertube.log') | ||
164 | |||
165 | while (true) { | ||
166 | const buf = await readFile(logfile) | ||
167 | |||
168 | const matches = buf.toString().match(new RegExp(str, 'g')) | ||
169 | if (matches && matches.length === count) return | ||
170 | |||
171 | await wait(1000) | ||
172 | } | ||
173 | } | ||
174 | |||
175 | // --------------------------------------------------------------------------- | ||
176 | |||
177 | export { | ||
178 | ServerInfo, | ||
179 | flushAndRunMultipleServers, | ||
180 | flushTests, | ||
181 | runServer, | ||
182 | killallServers, | ||
183 | reRunServer, | ||
184 | waitUntilLog | ||
185 | } | ||
diff --git a/server/tests/utils/server/stats.ts b/server/tests/utils/server/stats.ts deleted file mode 100644 index 01989d952..000000000 --- a/server/tests/utils/server/stats.ts +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | import { makeGetRequest } from '../' | ||
2 | |||
3 | function getStats (url: string, useCache = false) { | ||
4 | const path = '/api/v1/server/stats' | ||
5 | |||
6 | const query = { | ||
7 | t: useCache ? undefined : new Date().getTime() | ||
8 | } | ||
9 | |||
10 | return makeGetRequest({ | ||
11 | url, | ||
12 | path, | ||
13 | query, | ||
14 | statusCodeExpected: 200 | ||
15 | }) | ||
16 | } | ||
17 | |||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | export { | ||
21 | getStats | ||
22 | } | ||
diff --git a/server/tests/utils/users/accounts.ts b/server/tests/utils/users/accounts.ts deleted file mode 100644 index f82b8d906..000000000 --- a/server/tests/utils/users/accounts.ts +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { existsSync, readdir } from 'fs-extra' | ||
5 | import { join } from 'path' | ||
6 | import { Account } from '../../../../shared/models/actors' | ||
7 | import { root } from '../index' | ||
8 | import { makeGetRequest } from '../requests/requests' | ||
9 | |||
10 | function getAccountsList (url: string, sort = '-createdAt', statusCodeExpected = 200) { | ||
11 | const path = '/api/v1/accounts' | ||
12 | |||
13 | return makeGetRequest({ | ||
14 | url, | ||
15 | query: { sort }, | ||
16 | path, | ||
17 | statusCodeExpected | ||
18 | }) | ||
19 | } | ||
20 | |||
21 | function getAccount (url: string, accountName: string, statusCodeExpected = 200) { | ||
22 | const path = '/api/v1/accounts/' + accountName | ||
23 | |||
24 | return makeGetRequest({ | ||
25 | url, | ||
26 | path, | ||
27 | statusCodeExpected | ||
28 | }) | ||
29 | } | ||
30 | |||
31 | async function expectAccountFollows (url: string, nameWithDomain: string, followersCount: number, followingCount: number) { | ||
32 | const res = await getAccountsList(url) | ||
33 | const account = res.body.data.find((a: Account) => a.name + '@' + a.host === nameWithDomain) | ||
34 | |||
35 | const message = `${nameWithDomain} on ${url}` | ||
36 | expect(account.followersCount).to.equal(followersCount, message) | ||
37 | expect(account.followingCount).to.equal(followingCount, message) | ||
38 | } | ||
39 | |||
40 | async function checkActorFilesWereRemoved (actorUUID: string, serverNumber: number) { | ||
41 | const testDirectory = 'test' + serverNumber | ||
42 | |||
43 | for (const directory of [ 'avatars' ]) { | ||
44 | const directoryPath = join(root(), testDirectory, directory) | ||
45 | |||
46 | const directoryExists = existsSync(directoryPath) | ||
47 | expect(directoryExists).to.be.true | ||
48 | |||
49 | const files = await readdir(directoryPath) | ||
50 | for (const file of files) { | ||
51 | expect(file).to.not.contain(actorUUID) | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | // --------------------------------------------------------------------------- | ||
57 | |||
58 | export { | ||
59 | getAccount, | ||
60 | expectAccountFollows, | ||
61 | getAccountsList, | ||
62 | checkActorFilesWereRemoved | ||
63 | } | ||
diff --git a/server/tests/utils/users/login.ts b/server/tests/utils/users/login.ts deleted file mode 100644 index ddeb9df2a..000000000 --- a/server/tests/utils/users/login.ts +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | import { ServerInfo } from '../server/servers' | ||
4 | |||
5 | type Client = { id: string, secret: string } | ||
6 | type User = { username: string, password: string } | ||
7 | type Server = { url: string, client: Client, user: User } | ||
8 | |||
9 | function login (url: string, client: Client, user: User, expectedStatus = 200) { | ||
10 | const path = '/api/v1/users/token' | ||
11 | |||
12 | const body = { | ||
13 | client_id: client.id, | ||
14 | client_secret: client.secret, | ||
15 | username: user.username, | ||
16 | password: user.password, | ||
17 | response_type: 'code', | ||
18 | grant_type: 'password', | ||
19 | scope: 'upload' | ||
20 | } | ||
21 | |||
22 | return request(url) | ||
23 | .post(path) | ||
24 | .type('form') | ||
25 | .send(body) | ||
26 | .expect(expectedStatus) | ||
27 | } | ||
28 | |||
29 | async function serverLogin (server: Server) { | ||
30 | const res = await login(server.url, server.client, server.user, 200) | ||
31 | |||
32 | return res.body.access_token as string | ||
33 | } | ||
34 | |||
35 | async function userLogin (server: Server, user: User, expectedStatus = 200) { | ||
36 | const res = await login(server.url, server.client, user, expectedStatus) | ||
37 | |||
38 | return res.body.access_token as string | ||
39 | } | ||
40 | |||
41 | function setAccessTokensToServers (servers: ServerInfo[]) { | ||
42 | const tasks: Promise<any>[] = [] | ||
43 | |||
44 | for (const server of servers) { | ||
45 | const p = serverLogin(server).then(t => server.accessToken = t) | ||
46 | tasks.push(p) | ||
47 | } | ||
48 | |||
49 | return Promise.all(tasks) | ||
50 | } | ||
51 | |||
52 | // --------------------------------------------------------------------------- | ||
53 | |||
54 | export { | ||
55 | login, | ||
56 | serverLogin, | ||
57 | userLogin, | ||
58 | setAccessTokensToServers, | ||
59 | Server, | ||
60 | Client, | ||
61 | User | ||
62 | } | ||
diff --git a/server/tests/utils/users/user-subscriptions.ts b/server/tests/utils/users/user-subscriptions.ts deleted file mode 100644 index b0e7da7cc..000000000 --- a/server/tests/utils/users/user-subscriptions.ts +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | import { makeDeleteRequest, makeGetRequest, makePostBodyRequest } from '../' | ||
2 | |||
3 | function addUserSubscription (url: string, token: string, targetUri: string, statusCodeExpected = 204) { | ||
4 | const path = '/api/v1/users/me/subscriptions' | ||
5 | |||
6 | return makePostBodyRequest({ | ||
7 | url, | ||
8 | path, | ||
9 | token, | ||
10 | statusCodeExpected, | ||
11 | fields: { uri: targetUri } | ||
12 | }) | ||
13 | } | ||
14 | |||
15 | function listUserSubscriptions (url: string, token: string, sort = '-createdAt', statusCodeExpected = 200) { | ||
16 | const path = '/api/v1/users/me/subscriptions' | ||
17 | |||
18 | return makeGetRequest({ | ||
19 | url, | ||
20 | path, | ||
21 | token, | ||
22 | statusCodeExpected, | ||
23 | query: { sort } | ||
24 | }) | ||
25 | } | ||
26 | |||
27 | function listUserSubscriptionVideos (url: string, token: string, sort = '-createdAt', statusCodeExpected = 200) { | ||
28 | const path = '/api/v1/users/me/subscriptions/videos' | ||
29 | |||
30 | return makeGetRequest({ | ||
31 | url, | ||
32 | path, | ||
33 | token, | ||
34 | statusCodeExpected, | ||
35 | query: { sort } | ||
36 | }) | ||
37 | } | ||
38 | |||
39 | function getUserSubscription (url: string, token: string, uri: string, statusCodeExpected = 200) { | ||
40 | const path = '/api/v1/users/me/subscriptions/' + uri | ||
41 | |||
42 | return makeGetRequest({ | ||
43 | url, | ||
44 | path, | ||
45 | token, | ||
46 | statusCodeExpected | ||
47 | }) | ||
48 | } | ||
49 | |||
50 | function removeUserSubscription (url: string, token: string, uri: string, statusCodeExpected = 204) { | ||
51 | const path = '/api/v1/users/me/subscriptions/' + uri | ||
52 | |||
53 | return makeDeleteRequest({ | ||
54 | url, | ||
55 | path, | ||
56 | token, | ||
57 | statusCodeExpected | ||
58 | }) | ||
59 | } | ||
60 | |||
61 | function areSubscriptionsExist (url: string, token: string, uris: string[], statusCodeExpected = 200) { | ||
62 | const path = '/api/v1/users/me/subscriptions/exist' | ||
63 | |||
64 | return makeGetRequest({ | ||
65 | url, | ||
66 | path, | ||
67 | query: { 'uris[]': uris }, | ||
68 | token, | ||
69 | statusCodeExpected | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | // --------------------------------------------------------------------------- | ||
74 | |||
75 | export { | ||
76 | areSubscriptionsExist, | ||
77 | addUserSubscription, | ||
78 | listUserSubscriptions, | ||
79 | getUserSubscription, | ||
80 | listUserSubscriptionVideos, | ||
81 | removeUserSubscription | ||
82 | } | ||
diff --git a/server/tests/utils/users/users.ts b/server/tests/utils/users/users.ts deleted file mode 100644 index 41d8ce265..000000000 --- a/server/tests/utils/users/users.ts +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { makePostBodyRequest, makePutBodyRequest, updateAvatarRequest } from '../' | ||
3 | |||
4 | import { UserRole } from '../../../../shared/index' | ||
5 | import { NSFWPolicyType } from '../../../../shared/models/videos/nsfw-policy.type' | ||
6 | |||
7 | function createUser ( | ||
8 | url: string, | ||
9 | accessToken: string, | ||
10 | username: string, | ||
11 | password: string, | ||
12 | videoQuota = 1000000, | ||
13 | videoQuotaDaily = -1, | ||
14 | role: UserRole = UserRole.USER, | ||
15 | specialStatus = 200 | ||
16 | ) { | ||
17 | const path = '/api/v1/users' | ||
18 | const body = { | ||
19 | username, | ||
20 | password, | ||
21 | role, | ||
22 | email: username + '@example.com', | ||
23 | videoQuota, | ||
24 | videoQuotaDaily | ||
25 | } | ||
26 | |||
27 | return request(url) | ||
28 | .post(path) | ||
29 | .set('Accept', 'application/json') | ||
30 | .set('Authorization', 'Bearer ' + accessToken) | ||
31 | .send(body) | ||
32 | .expect(specialStatus) | ||
33 | } | ||
34 | |||
35 | function registerUser (url: string, username: string, password: string, specialStatus = 204) { | ||
36 | const path = '/api/v1/users/register' | ||
37 | const body = { | ||
38 | username, | ||
39 | password, | ||
40 | email: username + '@example.com' | ||
41 | } | ||
42 | |||
43 | return request(url) | ||
44 | .post(path) | ||
45 | .set('Accept', 'application/json') | ||
46 | .send(body) | ||
47 | .expect(specialStatus) | ||
48 | } | ||
49 | |||
50 | function getMyUserInformation (url: string, accessToken: string, specialStatus = 200) { | ||
51 | const path = '/api/v1/users/me' | ||
52 | |||
53 | return request(url) | ||
54 | .get(path) | ||
55 | .set('Accept', 'application/json') | ||
56 | .set('Authorization', 'Bearer ' + accessToken) | ||
57 | .expect(specialStatus) | ||
58 | .expect('Content-Type', /json/) | ||
59 | } | ||
60 | |||
61 | function deleteMe (url: string, accessToken: string, specialStatus = 204) { | ||
62 | const path = '/api/v1/users/me' | ||
63 | |||
64 | return request(url) | ||
65 | .delete(path) | ||
66 | .set('Accept', 'application/json') | ||
67 | .set('Authorization', 'Bearer ' + accessToken) | ||
68 | .expect(specialStatus) | ||
69 | } | ||
70 | |||
71 | function getMyUserVideoQuotaUsed (url: string, accessToken: string, specialStatus = 200) { | ||
72 | const path = '/api/v1/users/me/video-quota-used' | ||
73 | |||
74 | return request(url) | ||
75 | .get(path) | ||
76 | .set('Accept', 'application/json') | ||
77 | .set('Authorization', 'Bearer ' + accessToken) | ||
78 | .expect(specialStatus) | ||
79 | .expect('Content-Type', /json/) | ||
80 | } | ||
81 | |||
82 | function getUserInformation (url: string, accessToken: string, userId: number) { | ||
83 | const path = '/api/v1/users/' + userId | ||
84 | |||
85 | return request(url) | ||
86 | .get(path) | ||
87 | .set('Accept', 'application/json') | ||
88 | .set('Authorization', 'Bearer ' + accessToken) | ||
89 | .expect(200) | ||
90 | .expect('Content-Type', /json/) | ||
91 | } | ||
92 | |||
93 | function getMyUserVideoRating (url: string, accessToken: string, videoId: number | string, specialStatus = 200) { | ||
94 | const path = '/api/v1/users/me/videos/' + videoId + '/rating' | ||
95 | |||
96 | return request(url) | ||
97 | .get(path) | ||
98 | .set('Accept', 'application/json') | ||
99 | .set('Authorization', 'Bearer ' + accessToken) | ||
100 | .expect(specialStatus) | ||
101 | .expect('Content-Type', /json/) | ||
102 | } | ||
103 | |||
104 | function getUsersList (url: string, accessToken: string) { | ||
105 | const path = '/api/v1/users' | ||
106 | |||
107 | return request(url) | ||
108 | .get(path) | ||
109 | .set('Accept', 'application/json') | ||
110 | .set('Authorization', 'Bearer ' + accessToken) | ||
111 | .expect(200) | ||
112 | .expect('Content-Type', /json/) | ||
113 | } | ||
114 | |||
115 | function getUsersListPaginationAndSort (url: string, accessToken: string, start: number, count: number, sort: string) { | ||
116 | const path = '/api/v1/users' | ||
117 | |||
118 | return request(url) | ||
119 | .get(path) | ||
120 | .query({ start }) | ||
121 | .query({ count }) | ||
122 | .query({ sort }) | ||
123 | .set('Accept', 'application/json') | ||
124 | .set('Authorization', 'Bearer ' + accessToken) | ||
125 | .expect(200) | ||
126 | .expect('Content-Type', /json/) | ||
127 | } | ||
128 | |||
129 | function removeUser (url: string, userId: number | string, accessToken: string, expectedStatus = 204) { | ||
130 | const path = '/api/v1/users' | ||
131 | |||
132 | return request(url) | ||
133 | .delete(path + '/' + userId) | ||
134 | .set('Accept', 'application/json') | ||
135 | .set('Authorization', 'Bearer ' + accessToken) | ||
136 | .expect(expectedStatus) | ||
137 | } | ||
138 | |||
139 | function blockUser (url: string, userId: number | string, accessToken: string, expectedStatus = 204, reason?: string) { | ||
140 | const path = '/api/v1/users' | ||
141 | let body: any | ||
142 | if (reason) body = { reason } | ||
143 | |||
144 | return request(url) | ||
145 | .post(path + '/' + userId + '/block') | ||
146 | .send(body) | ||
147 | .set('Accept', 'application/json') | ||
148 | .set('Authorization', 'Bearer ' + accessToken) | ||
149 | .expect(expectedStatus) | ||
150 | } | ||
151 | |||
152 | function unblockUser (url: string, userId: number | string, accessToken: string, expectedStatus = 204) { | ||
153 | const path = '/api/v1/users' | ||
154 | |||
155 | return request(url) | ||
156 | .post(path + '/' + userId + '/unblock') | ||
157 | .set('Accept', 'application/json') | ||
158 | .set('Authorization', 'Bearer ' + accessToken) | ||
159 | .expect(expectedStatus) | ||
160 | } | ||
161 | |||
162 | function updateMyUser (options: { | ||
163 | url: string | ||
164 | accessToken: string, | ||
165 | currentPassword?: string, | ||
166 | newPassword?: string, | ||
167 | nsfwPolicy?: NSFWPolicyType, | ||
168 | email?: string, | ||
169 | autoPlayVideo?: boolean | ||
170 | displayName?: string, | ||
171 | description?: string | ||
172 | }) { | ||
173 | const path = '/api/v1/users/me' | ||
174 | |||
175 | const toSend = {} | ||
176 | if (options.currentPassword !== undefined && options.currentPassword !== null) toSend['currentPassword'] = options.currentPassword | ||
177 | if (options.newPassword !== undefined && options.newPassword !== null) toSend['password'] = options.newPassword | ||
178 | if (options.nsfwPolicy !== undefined && options.nsfwPolicy !== null) toSend['nsfwPolicy'] = options.nsfwPolicy | ||
179 | if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo | ||
180 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | ||
181 | if (options.description !== undefined && options.description !== null) toSend['description'] = options.description | ||
182 | if (options.displayName !== undefined && options.displayName !== null) toSend['displayName'] = options.displayName | ||
183 | |||
184 | return makePutBodyRequest({ | ||
185 | url: options.url, | ||
186 | path, | ||
187 | token: options.accessToken, | ||
188 | fields: toSend, | ||
189 | statusCodeExpected: 204 | ||
190 | }) | ||
191 | } | ||
192 | |||
193 | function updateMyAvatar (options: { | ||
194 | url: string, | ||
195 | accessToken: string, | ||
196 | fixture: string | ||
197 | }) { | ||
198 | const path = '/api/v1/users/me/avatar/pick' | ||
199 | |||
200 | return updateAvatarRequest(Object.assign(options, { path })) | ||
201 | } | ||
202 | |||
203 | function updateUser (options: { | ||
204 | url: string | ||
205 | userId: number, | ||
206 | accessToken: string, | ||
207 | email?: string, | ||
208 | videoQuota?: number, | ||
209 | videoQuotaDaily?: number, | ||
210 | role?: UserRole | ||
211 | }) { | ||
212 | const path = '/api/v1/users/' + options.userId | ||
213 | |||
214 | const toSend = {} | ||
215 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | ||
216 | if (options.videoQuota !== undefined && options.videoQuota !== null) toSend['videoQuota'] = options.videoQuota | ||
217 | if (options.videoQuotaDaily !== undefined && options.videoQuotaDaily !== null) toSend['videoQuotaDaily'] = options.videoQuotaDaily | ||
218 | if (options.role !== undefined && options.role !== null) toSend['role'] = options.role | ||
219 | |||
220 | return makePutBodyRequest({ | ||
221 | url: options.url, | ||
222 | path, | ||
223 | token: options.accessToken, | ||
224 | fields: toSend, | ||
225 | statusCodeExpected: 204 | ||
226 | }) | ||
227 | } | ||
228 | |||
229 | function askResetPassword (url: string, email: string) { | ||
230 | const path = '/api/v1/users/ask-reset-password' | ||
231 | |||
232 | return makePostBodyRequest({ | ||
233 | url, | ||
234 | path, | ||
235 | fields: { email }, | ||
236 | statusCodeExpected: 204 | ||
237 | }) | ||
238 | } | ||
239 | |||
240 | function resetPassword (url: string, userId: number, verificationString: string, password: string, statusCodeExpected = 204) { | ||
241 | const path = '/api/v1/users/' + userId + '/reset-password' | ||
242 | |||
243 | return makePostBodyRequest({ | ||
244 | url, | ||
245 | path, | ||
246 | fields: { password, verificationString }, | ||
247 | statusCodeExpected | ||
248 | }) | ||
249 | } | ||
250 | |||
251 | function askSendVerifyEmail (url: string, email: string) { | ||
252 | const path = '/api/v1/users/ask-send-verify-email' | ||
253 | |||
254 | return makePostBodyRequest({ | ||
255 | url, | ||
256 | path, | ||
257 | fields: { email }, | ||
258 | statusCodeExpected: 204 | ||
259 | }) | ||
260 | } | ||
261 | |||
262 | function verifyEmail (url: string, userId: number, verificationString: string, statusCodeExpected = 204) { | ||
263 | const path = '/api/v1/users/' + userId + '/verify-email' | ||
264 | |||
265 | return makePostBodyRequest({ | ||
266 | url, | ||
267 | path, | ||
268 | fields: { verificationString }, | ||
269 | statusCodeExpected | ||
270 | }) | ||
271 | } | ||
272 | |||
273 | // --------------------------------------------------------------------------- | ||
274 | |||
275 | export { | ||
276 | createUser, | ||
277 | registerUser, | ||
278 | getMyUserInformation, | ||
279 | getMyUserVideoRating, | ||
280 | deleteMe, | ||
281 | getMyUserVideoQuotaUsed, | ||
282 | getUsersList, | ||
283 | getUsersListPaginationAndSort, | ||
284 | removeUser, | ||
285 | updateUser, | ||
286 | updateMyUser, | ||
287 | getUserInformation, | ||
288 | blockUser, | ||
289 | unblockUser, | ||
290 | askResetPassword, | ||
291 | resetPassword, | ||
292 | updateMyAvatar, | ||
293 | askSendVerifyEmail, | ||
294 | verifyEmail | ||
295 | } | ||
diff --git a/server/tests/utils/videos/services.ts b/server/tests/utils/videos/services.ts deleted file mode 100644 index 1a53dd4cf..000000000 --- a/server/tests/utils/videos/services.ts +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | function getOEmbed (url: string, oembedUrl: string, format?: string, maxHeight?: number, maxWidth?: number) { | ||
4 | const path = '/services/oembed' | ||
5 | const query = { | ||
6 | url: oembedUrl, | ||
7 | format, | ||
8 | maxheight: maxHeight, | ||
9 | maxwidth: maxWidth | ||
10 | } | ||
11 | |||
12 | return request(url) | ||
13 | .get(path) | ||
14 | .query(query) | ||
15 | .set('Accept', 'application/json') | ||
16 | .expect(200) | ||
17 | } | ||
18 | |||
19 | // --------------------------------------------------------------------------- | ||
20 | |||
21 | export { | ||
22 | getOEmbed | ||
23 | } | ||
diff --git a/server/tests/utils/videos/video-abuses.ts b/server/tests/utils/videos/video-abuses.ts deleted file mode 100644 index 14907e6a0..000000000 --- a/server/tests/utils/videos/video-abuses.ts +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { VideoAbuseUpdate } from '../../../../shared/models/videos/abuse/video-abuse-update.model' | ||
3 | import { makeDeleteRequest, makePutBodyRequest } from '..' | ||
4 | |||
5 | function reportVideoAbuse (url: string, token: string, videoId: number | string, reason: string, specialStatus = 200) { | ||
6 | const path = '/api/v1/videos/' + videoId + '/abuse' | ||
7 | |||
8 | return request(url) | ||
9 | .post(path) | ||
10 | .set('Accept', 'application/json') | ||
11 | .set('Authorization', 'Bearer ' + token) | ||
12 | .send({ reason }) | ||
13 | .expect(specialStatus) | ||
14 | } | ||
15 | |||
16 | function getVideoAbusesList (url: string, token: string) { | ||
17 | const path = '/api/v1/videos/abuse' | ||
18 | |||
19 | return request(url) | ||
20 | .get(path) | ||
21 | .query({ sort: 'createdAt' }) | ||
22 | .set('Accept', 'application/json') | ||
23 | .set('Authorization', 'Bearer ' + token) | ||
24 | .expect(200) | ||
25 | .expect('Content-Type', /json/) | ||
26 | } | ||
27 | |||
28 | function updateVideoAbuse ( | ||
29 | url: string, | ||
30 | token: string, | ||
31 | videoId: string | number, | ||
32 | videoAbuseId: number, | ||
33 | body: VideoAbuseUpdate, | ||
34 | statusCodeExpected = 204 | ||
35 | ) { | ||
36 | const path = '/api/v1/videos/' + videoId + '/abuse/' + videoAbuseId | ||
37 | |||
38 | return makePutBodyRequest({ | ||
39 | url, | ||
40 | token, | ||
41 | path, | ||
42 | fields: body, | ||
43 | statusCodeExpected | ||
44 | }) | ||
45 | } | ||
46 | |||
47 | function deleteVideoAbuse (url: string, token: string, videoId: string | number, videoAbuseId: number, statusCodeExpected = 204) { | ||
48 | const path = '/api/v1/videos/' + videoId + '/abuse/' + videoAbuseId | ||
49 | |||
50 | return makeDeleteRequest({ | ||
51 | url, | ||
52 | token, | ||
53 | path, | ||
54 | statusCodeExpected | ||
55 | }) | ||
56 | } | ||
57 | |||
58 | // --------------------------------------------------------------------------- | ||
59 | |||
60 | export { | ||
61 | reportVideoAbuse, | ||
62 | getVideoAbusesList, | ||
63 | updateVideoAbuse, | ||
64 | deleteVideoAbuse | ||
65 | } | ||
diff --git a/server/tests/utils/videos/video-blacklist.ts b/server/tests/utils/videos/video-blacklist.ts deleted file mode 100644 index 2c176fde0..000000000 --- a/server/tests/utils/videos/video-blacklist.ts +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | function addVideoToBlacklist (url: string, token: string, videoId: number | string, reason?: string, specialStatus = 204) { | ||
4 | const path = '/api/v1/videos/' + videoId + '/blacklist' | ||
5 | |||
6 | return request(url) | ||
7 | .post(path) | ||
8 | .send({ reason }) | ||
9 | .set('Accept', 'application/json') | ||
10 | .set('Authorization', 'Bearer ' + token) | ||
11 | .expect(specialStatus) | ||
12 | } | ||
13 | |||
14 | function updateVideoBlacklist (url: string, token: string, videoId: number, reason?: string, specialStatus = 204) { | ||
15 | const path = '/api/v1/videos/' + videoId + '/blacklist' | ||
16 | |||
17 | return request(url) | ||
18 | .put(path) | ||
19 | .send({ reason }) | ||
20 | .set('Accept', 'application/json') | ||
21 | .set('Authorization', 'Bearer ' + token) | ||
22 | .expect(specialStatus) | ||
23 | } | ||
24 | |||
25 | function removeVideoFromBlacklist (url: string, token: string, videoId: number | string, specialStatus = 204) { | ||
26 | const path = '/api/v1/videos/' + videoId + '/blacklist' | ||
27 | |||
28 | return request(url) | ||
29 | .delete(path) | ||
30 | .set('Accept', 'application/json') | ||
31 | .set('Authorization', 'Bearer ' + token) | ||
32 | .expect(specialStatus) | ||
33 | } | ||
34 | |||
35 | function getBlacklistedVideosList (url: string, token: string, specialStatus = 200) { | ||
36 | const path = '/api/v1/videos/blacklist/' | ||
37 | |||
38 | return request(url) | ||
39 | .get(path) | ||
40 | .query({ sort: 'createdAt' }) | ||
41 | .set('Accept', 'application/json') | ||
42 | .set('Authorization', 'Bearer ' + token) | ||
43 | .expect(specialStatus) | ||
44 | .expect('Content-Type', /json/) | ||
45 | } | ||
46 | |||
47 | function getSortedBlacklistedVideosList (url: string, token: string, sort: string, specialStatus = 200) { | ||
48 | const path = '/api/v1/videos/blacklist/' | ||
49 | |||
50 | return request(url) | ||
51 | .get(path) | ||
52 | .query({ sort: sort }) | ||
53 | .set('Accept', 'application/json') | ||
54 | .set('Authorization', 'Bearer ' + token) | ||
55 | .expect(specialStatus) | ||
56 | .expect('Content-Type', /json/) | ||
57 | } | ||
58 | |||
59 | // --------------------------------------------------------------------------- | ||
60 | |||
61 | export { | ||
62 | addVideoToBlacklist, | ||
63 | removeVideoFromBlacklist, | ||
64 | getBlacklistedVideosList, | ||
65 | getSortedBlacklistedVideosList, | ||
66 | updateVideoBlacklist | ||
67 | } | ||
diff --git a/server/tests/utils/videos/video-captions.ts b/server/tests/utils/videos/video-captions.ts deleted file mode 100644 index 41e52be07..000000000 --- a/server/tests/utils/videos/video-captions.ts +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | import { makeDeleteRequest, makeGetRequest } from '../' | ||
2 | import { buildAbsoluteFixturePath, makeUploadRequest } from '../index' | ||
3 | import * as request from 'supertest' | ||
4 | import * as chai from 'chai' | ||
5 | |||
6 | const expect = chai.expect | ||
7 | |||
8 | function createVideoCaption (args: { | ||
9 | url: string, | ||
10 | accessToken: string | ||
11 | videoId: string | number | ||
12 | language: string | ||
13 | fixture: string, | ||
14 | mimeType?: string, | ||
15 | statusCodeExpected?: number | ||
16 | }) { | ||
17 | const path = '/api/v1/videos/' + args.videoId + '/captions/' + args.language | ||
18 | |||
19 | const captionfile = buildAbsoluteFixturePath(args.fixture) | ||
20 | const captionfileAttach = args.mimeType ? [ captionfile, { contentType: args.mimeType } ] : captionfile | ||
21 | |||
22 | return makeUploadRequest({ | ||
23 | method: 'PUT', | ||
24 | url: args.url, | ||
25 | path, | ||
26 | token: args.accessToken, | ||
27 | fields: {}, | ||
28 | attaches: { | ||
29 | captionfile: captionfileAttach | ||
30 | }, | ||
31 | statusCodeExpected: args.statusCodeExpected || 204 | ||
32 | }) | ||
33 | } | ||
34 | |||
35 | function listVideoCaptions (url: string, videoId: string | number) { | ||
36 | const path = '/api/v1/videos/' + videoId + '/captions' | ||
37 | |||
38 | return makeGetRequest({ | ||
39 | url, | ||
40 | path, | ||
41 | statusCodeExpected: 200 | ||
42 | }) | ||
43 | } | ||
44 | |||
45 | function deleteVideoCaption (url: string, token: string, videoId: string | number, language: string) { | ||
46 | const path = '/api/v1/videos/' + videoId + '/captions/' + language | ||
47 | |||
48 | return makeDeleteRequest({ | ||
49 | url, | ||
50 | token, | ||
51 | path, | ||
52 | statusCodeExpected: 204 | ||
53 | }) | ||
54 | } | ||
55 | |||
56 | async function testCaptionFile (url: string, captionPath: string, containsString: string) { | ||
57 | const res = await request(url) | ||
58 | .get(captionPath) | ||
59 | .expect(200) | ||
60 | |||
61 | expect(res.text).to.contain(containsString) | ||
62 | } | ||
63 | |||
64 | // --------------------------------------------------------------------------- | ||
65 | |||
66 | export { | ||
67 | createVideoCaption, | ||
68 | listVideoCaptions, | ||
69 | testCaptionFile, | ||
70 | deleteVideoCaption | ||
71 | } | ||
diff --git a/server/tests/utils/videos/video-change-ownership.ts b/server/tests/utils/videos/video-change-ownership.ts deleted file mode 100644 index f288692ea..000000000 --- a/server/tests/utils/videos/video-change-ownership.ts +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | |||
3 | function changeVideoOwnership (url: string, token: string, videoId: number | string, username) { | ||
4 | const path = '/api/v1/videos/' + videoId + '/give-ownership' | ||
5 | |||
6 | return request(url) | ||
7 | .post(path) | ||
8 | .set('Accept', 'application/json') | ||
9 | .set('Authorization', 'Bearer ' + token) | ||
10 | .send({ username }) | ||
11 | .expect(204) | ||
12 | } | ||
13 | |||
14 | function getVideoChangeOwnershipList (url: string, token: string) { | ||
15 | const path = '/api/v1/videos/ownership' | ||
16 | |||
17 | return request(url) | ||
18 | .get(path) | ||
19 | .query({ sort: '-createdAt' }) | ||
20 | .set('Accept', 'application/json') | ||
21 | .set('Authorization', 'Bearer ' + token) | ||
22 | .expect(200) | ||
23 | .expect('Content-Type', /json/) | ||
24 | } | ||
25 | |||
26 | function acceptChangeOwnership (url: string, token: string, ownershipId: string, channelId: number, expectedStatus = 204) { | ||
27 | const path = '/api/v1/videos/ownership/' + ownershipId + '/accept' | ||
28 | |||
29 | return request(url) | ||
30 | .post(path) | ||
31 | .set('Accept', 'application/json') | ||
32 | .set('Authorization', 'Bearer ' + token) | ||
33 | .send({ channelId }) | ||
34 | .expect(expectedStatus) | ||
35 | } | ||
36 | |||
37 | function refuseChangeOwnership (url: string, token: string, ownershipId: string, expectedStatus = 204) { | ||
38 | const path = '/api/v1/videos/ownership/' + ownershipId + '/refuse' | ||
39 | |||
40 | return request(url) | ||
41 | .post(path) | ||
42 | .set('Accept', 'application/json') | ||
43 | .set('Authorization', 'Bearer ' + token) | ||
44 | .expect(expectedStatus) | ||
45 | } | ||
46 | |||
47 | // --------------------------------------------------------------------------- | ||
48 | |||
49 | export { | ||
50 | changeVideoOwnership, | ||
51 | getVideoChangeOwnershipList, | ||
52 | acceptChangeOwnership, | ||
53 | refuseChangeOwnership | ||
54 | } | ||
diff --git a/server/tests/utils/videos/video-channels.ts b/server/tests/utils/videos/video-channels.ts deleted file mode 100644 index 092985777..000000000 --- a/server/tests/utils/videos/video-channels.ts +++ /dev/null | |||
@@ -1,118 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared/models/videos' | ||
3 | import { updateAvatarRequest } from '../index' | ||
4 | |||
5 | function getVideoChannelsList (url: string, start: number, count: number, sort?: string) { | ||
6 | const path = '/api/v1/video-channels' | ||
7 | |||
8 | const req = request(url) | ||
9 | .get(path) | ||
10 | .query({ start: start }) | ||
11 | .query({ count: count }) | ||
12 | |||
13 | if (sort) req.query({ sort }) | ||
14 | |||
15 | return req.set('Accept', 'application/json') | ||
16 | .expect(200) | ||
17 | .expect('Content-Type', /json/) | ||
18 | } | ||
19 | |||
20 | function getAccountVideoChannelsList (url: string, accountName: string, specialStatus = 200) { | ||
21 | const path = '/api/v1/accounts/' + accountName + '/video-channels' | ||
22 | |||
23 | return request(url) | ||
24 | .get(path) | ||
25 | .set('Accept', 'application/json') | ||
26 | .expect(specialStatus) | ||
27 | .expect('Content-Type', /json/) | ||
28 | } | ||
29 | |||
30 | function addVideoChannel ( | ||
31 | url: string, | ||
32 | token: string, | ||
33 | videoChannelAttributesArg: VideoChannelCreate, | ||
34 | expectedStatus = 200 | ||
35 | ) { | ||
36 | const path = '/api/v1/video-channels/' | ||
37 | |||
38 | // Default attributes | ||
39 | let attributes = { | ||
40 | displayName: 'my super video channel', | ||
41 | description: 'my super channel description', | ||
42 | support: 'my super channel support' | ||
43 | } | ||
44 | attributes = Object.assign(attributes, videoChannelAttributesArg) | ||
45 | |||
46 | return request(url) | ||
47 | .post(path) | ||
48 | .send(attributes) | ||
49 | .set('Accept', 'application/json') | ||
50 | .set('Authorization', 'Bearer ' + token) | ||
51 | .expect(expectedStatus) | ||
52 | } | ||
53 | |||
54 | function updateVideoChannel ( | ||
55 | url: string, | ||
56 | token: string, | ||
57 | channelName: string, | ||
58 | attributes: VideoChannelUpdate, | ||
59 | expectedStatus = 204 | ||
60 | ) { | ||
61 | const body = {} | ||
62 | const path = '/api/v1/video-channels/' + channelName | ||
63 | |||
64 | if (attributes.displayName) body['displayName'] = attributes.displayName | ||
65 | if (attributes.description) body['description'] = attributes.description | ||
66 | if (attributes.support) body['support'] = attributes.support | ||
67 | |||
68 | return request(url) | ||
69 | .put(path) | ||
70 | .send(body) | ||
71 | .set('Accept', 'application/json') | ||
72 | .set('Authorization', 'Bearer ' + token) | ||
73 | .expect(expectedStatus) | ||
74 | } | ||
75 | |||
76 | function deleteVideoChannel (url: string, token: string, channelName: string, expectedStatus = 204) { | ||
77 | const path = '/api/v1/video-channels/' + channelName | ||
78 | |||
79 | return request(url) | ||
80 | .delete(path) | ||
81 | .set('Accept', 'application/json') | ||
82 | .set('Authorization', 'Bearer ' + token) | ||
83 | .expect(expectedStatus) | ||
84 | } | ||
85 | |||
86 | function getVideoChannel (url: string, channelName: string) { | ||
87 | const path = '/api/v1/video-channels/' + channelName | ||
88 | |||
89 | return request(url) | ||
90 | .get(path) | ||
91 | .set('Accept', 'application/json') | ||
92 | .expect(200) | ||
93 | .expect('Content-Type', /json/) | ||
94 | } | ||
95 | |||
96 | function updateVideoChannelAvatar (options: { | ||
97 | url: string, | ||
98 | accessToken: string, | ||
99 | fixture: string, | ||
100 | videoChannelName: string | number | ||
101 | }) { | ||
102 | |||
103 | const path = '/api/v1/video-channels/' + options.videoChannelName + '/avatar/pick' | ||
104 | |||
105 | return updateAvatarRequest(Object.assign(options, { path })) | ||
106 | } | ||
107 | |||
108 | // --------------------------------------------------------------------------- | ||
109 | |||
110 | export { | ||
111 | updateVideoChannelAvatar, | ||
112 | getVideoChannelsList, | ||
113 | getAccountVideoChannelsList, | ||
114 | addVideoChannel, | ||
115 | updateVideoChannel, | ||
116 | deleteVideoChannel, | ||
117 | getVideoChannel | ||
118 | } | ||
diff --git a/server/tests/utils/videos/video-comments.ts b/server/tests/utils/videos/video-comments.ts deleted file mode 100644 index 1b9ee452e..000000000 --- a/server/tests/utils/videos/video-comments.ts +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { makeDeleteRequest } from '../' | ||
3 | |||
4 | function getVideoCommentThreads (url: string, videoId: number | string, start: number, count: number, sort?: string) { | ||
5 | const path = '/api/v1/videos/' + videoId + '/comment-threads' | ||
6 | |||
7 | const req = request(url) | ||
8 | .get(path) | ||
9 | .query({ start: start }) | ||
10 | .query({ count: count }) | ||
11 | |||
12 | if (sort) req.query({ sort }) | ||
13 | |||
14 | return req.set('Accept', 'application/json') | ||
15 | .expect(200) | ||
16 | .expect('Content-Type', /json/) | ||
17 | } | ||
18 | |||
19 | function getVideoThreadComments (url: string, videoId: number | string, threadId: number) { | ||
20 | const path = '/api/v1/videos/' + videoId + '/comment-threads/' + threadId | ||
21 | |||
22 | return request(url) | ||
23 | .get(path) | ||
24 | .set('Accept', 'application/json') | ||
25 | .expect(200) | ||
26 | .expect('Content-Type', /json/) | ||
27 | } | ||
28 | |||
29 | function addVideoCommentThread (url: string, token: string, videoId: number | string, text: string, expectedStatus = 200) { | ||
30 | const path = '/api/v1/videos/' + videoId + '/comment-threads' | ||
31 | |||
32 | return request(url) | ||
33 | .post(path) | ||
34 | .send({ text }) | ||
35 | .set('Accept', 'application/json') | ||
36 | .set('Authorization', 'Bearer ' + token) | ||
37 | .expect(expectedStatus) | ||
38 | } | ||
39 | |||
40 | function addVideoCommentReply ( | ||
41 | url: string, | ||
42 | token: string, | ||
43 | videoId: number | string, | ||
44 | inReplyToCommentId: number, | ||
45 | text: string, | ||
46 | expectedStatus = 200 | ||
47 | ) { | ||
48 | const path = '/api/v1/videos/' + videoId + '/comments/' + inReplyToCommentId | ||
49 | |||
50 | return request(url) | ||
51 | .post(path) | ||
52 | .send({ text }) | ||
53 | .set('Accept', 'application/json') | ||
54 | .set('Authorization', 'Bearer ' + token) | ||
55 | .expect(expectedStatus) | ||
56 | } | ||
57 | |||
58 | function deleteVideoComment ( | ||
59 | url: string, | ||
60 | token: string, | ||
61 | videoId: number | string, | ||
62 | commentId: number, | ||
63 | statusCodeExpected = 204 | ||
64 | ) { | ||
65 | const path = '/api/v1/videos/' + videoId + '/comments/' + commentId | ||
66 | |||
67 | return makeDeleteRequest({ | ||
68 | url, | ||
69 | path, | ||
70 | token, | ||
71 | statusCodeExpected | ||
72 | }) | ||
73 | } | ||
74 | |||
75 | // --------------------------------------------------------------------------- | ||
76 | |||
77 | export { | ||
78 | getVideoCommentThreads, | ||
79 | getVideoThreadComments, | ||
80 | addVideoCommentThread, | ||
81 | addVideoCommentReply, | ||
82 | deleteVideoComment | ||
83 | } | ||
diff --git a/server/tests/utils/videos/video-history.ts b/server/tests/utils/videos/video-history.ts deleted file mode 100644 index 7635478f7..000000000 --- a/server/tests/utils/videos/video-history.ts +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | import { makePutBodyRequest } from '../requests/requests' | ||
2 | |||
3 | function userWatchVideo (url: string, token: string, videoId: number | string, currentTime: number) { | ||
4 | const path = '/api/v1/videos/' + videoId + '/watching' | ||
5 | const fields = { currentTime } | ||
6 | |||
7 | return makePutBodyRequest({ url, path, token, fields, statusCodeExpected: 204 }) | ||
8 | } | ||
9 | |||
10 | // --------------------------------------------------------------------------- | ||
11 | |||
12 | export { | ||
13 | userWatchVideo | ||
14 | } | ||
diff --git a/server/tests/utils/videos/video-imports.ts b/server/tests/utils/videos/video-imports.ts deleted file mode 100644 index 59dfd481a..000000000 --- a/server/tests/utils/videos/video-imports.ts +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | import { VideoImportCreate } from '../../../../shared/models/videos' | ||
2 | import { makeGetRequest, makeUploadRequest } from '..' | ||
3 | |||
4 | function getYoutubeVideoUrl () { | ||
5 | return 'https://youtu.be/msX3jv1XdvM' | ||
6 | } | ||
7 | |||
8 | function getMagnetURI () { | ||
9 | // tslint:disable:max-line-length | ||
10 | return 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4' | ||
11 | } | ||
12 | |||
13 | function importVideo (url: string, token: string, attributes: VideoImportCreate) { | ||
14 | const path = '/api/v1/videos/imports' | ||
15 | |||
16 | let attaches: any = {} | ||
17 | if (attributes.torrentfile) attaches = { torrentfile: attributes.torrentfile } | ||
18 | |||
19 | return makeUploadRequest({ | ||
20 | url, | ||
21 | path, | ||
22 | token, | ||
23 | attaches, | ||
24 | fields: attributes, | ||
25 | statusCodeExpected: 200 | ||
26 | }) | ||
27 | } | ||
28 | |||
29 | function getMyVideoImports (url: string, token: string, sort?: string) { | ||
30 | const path = '/api/v1/users/me/videos/imports' | ||
31 | |||
32 | const query = {} | ||
33 | if (sort) query['sort'] = sort | ||
34 | |||
35 | return makeGetRequest({ | ||
36 | url, | ||
37 | query, | ||
38 | path, | ||
39 | token, | ||
40 | statusCodeExpected: 200 | ||
41 | }) | ||
42 | } | ||
43 | |||
44 | // --------------------------------------------------------------------------- | ||
45 | |||
46 | export { | ||
47 | getYoutubeVideoUrl, | ||
48 | importVideo, | ||
49 | getMagnetURI, | ||
50 | getMyVideoImports | ||
51 | } | ||
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts deleted file mode 100644 index bc878b039..000000000 --- a/server/tests/utils/videos/videos.ts +++ /dev/null | |||
@@ -1,582 +0,0 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import { expect } from 'chai' | ||
4 | import { existsSync, readdir, readFile } from 'fs-extra' | ||
5 | import * as parseTorrent from 'parse-torrent' | ||
6 | import { extname, join } from 'path' | ||
7 | import * as request from 'supertest' | ||
8 | import { | ||
9 | buildAbsoluteFixturePath, | ||
10 | getMyUserInformation, | ||
11 | immutableAssign, | ||
12 | makeGetRequest, | ||
13 | makePutBodyRequest, | ||
14 | makeUploadRequest, | ||
15 | root, | ||
16 | ServerInfo, | ||
17 | testImage | ||
18 | } from '../' | ||
19 | import { VideoDetails, VideoPrivacy } from '../../../../shared/models/videos' | ||
20 | import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers' | ||
21 | import { dateIsValid, webtorrentAdd } from '../index' | ||
22 | |||
23 | type VideoAttributes = { | ||
24 | name?: string | ||
25 | category?: number | ||
26 | licence?: number | ||
27 | language?: string | ||
28 | nsfw?: boolean | ||
29 | commentsEnabled?: boolean | ||
30 | downloadEnabled?: boolean | ||
31 | waitTranscoding?: boolean | ||
32 | description?: string | ||
33 | tags?: string[] | ||
34 | channelId?: number | ||
35 | privacy?: VideoPrivacy | ||
36 | fixture?: string | ||
37 | thumbnailfile?: string | ||
38 | previewfile?: string | ||
39 | scheduleUpdate?: { | ||
40 | updateAt: string | ||
41 | privacy?: VideoPrivacy | ||
42 | } | ||
43 | } | ||
44 | |||
45 | function getVideoCategories (url: string) { | ||
46 | const path = '/api/v1/videos/categories' | ||
47 | |||
48 | return makeGetRequest({ | ||
49 | url, | ||
50 | path, | ||
51 | statusCodeExpected: 200 | ||
52 | }) | ||
53 | } | ||
54 | |||
55 | function getVideoLicences (url: string) { | ||
56 | const path = '/api/v1/videos/licences' | ||
57 | |||
58 | return makeGetRequest({ | ||
59 | url, | ||
60 | path, | ||
61 | statusCodeExpected: 200 | ||
62 | }) | ||
63 | } | ||
64 | |||
65 | function getVideoLanguages (url: string) { | ||
66 | const path = '/api/v1/videos/languages' | ||
67 | |||
68 | return makeGetRequest({ | ||
69 | url, | ||
70 | path, | ||
71 | statusCodeExpected: 200 | ||
72 | }) | ||
73 | } | ||
74 | |||
75 | function getVideoPrivacies (url: string) { | ||
76 | const path = '/api/v1/videos/privacies' | ||
77 | |||
78 | return makeGetRequest({ | ||
79 | url, | ||
80 | path, | ||
81 | statusCodeExpected: 200 | ||
82 | }) | ||
83 | } | ||
84 | |||
85 | function getVideo (url: string, id: number | string, expectedStatus = 200) { | ||
86 | const path = '/api/v1/videos/' + id | ||
87 | |||
88 | return request(url) | ||
89 | .get(path) | ||
90 | .set('Accept', 'application/json') | ||
91 | .expect(expectedStatus) | ||
92 | } | ||
93 | |||
94 | function viewVideo (url: string, id: number | string, expectedStatus = 204, xForwardedFor?: string) { | ||
95 | const path = '/api/v1/videos/' + id + '/views' | ||
96 | |||
97 | const req = request(url) | ||
98 | .post(path) | ||
99 | .set('Accept', 'application/json') | ||
100 | |||
101 | if (xForwardedFor) { | ||
102 | req.set('X-Forwarded-For', xForwardedFor) | ||
103 | } | ||
104 | |||
105 | return req.expect(expectedStatus) | ||
106 | } | ||
107 | |||
108 | function getVideoWithToken (url: string, token: string, id: number | string, expectedStatus = 200) { | ||
109 | const path = '/api/v1/videos/' + id | ||
110 | |||
111 | return request(url) | ||
112 | .get(path) | ||
113 | .set('Authorization', 'Bearer ' + token) | ||
114 | .set('Accept', 'application/json') | ||
115 | .expect(expectedStatus) | ||
116 | } | ||
117 | |||
118 | function getVideoDescription (url: string, descriptionPath: string) { | ||
119 | return request(url) | ||
120 | .get(descriptionPath) | ||
121 | .set('Accept', 'application/json') | ||
122 | .expect(200) | ||
123 | .expect('Content-Type', /json/) | ||
124 | } | ||
125 | |||
126 | function getVideosList (url: string) { | ||
127 | const path = '/api/v1/videos' | ||
128 | |||
129 | return request(url) | ||
130 | .get(path) | ||
131 | .query({ sort: 'name' }) | ||
132 | .set('Accept', 'application/json') | ||
133 | .expect(200) | ||
134 | .expect('Content-Type', /json/) | ||
135 | } | ||
136 | |||
137 | function getVideosListWithToken (url: string, token: string, query: { nsfw?: boolean } = {}) { | ||
138 | const path = '/api/v1/videos' | ||
139 | |||
140 | return request(url) | ||
141 | .get(path) | ||
142 | .set('Authorization', 'Bearer ' + token) | ||
143 | .query(immutableAssign(query, { sort: 'name' })) | ||
144 | .set('Accept', 'application/json') | ||
145 | .expect(200) | ||
146 | .expect('Content-Type', /json/) | ||
147 | } | ||
148 | |||
149 | function getLocalVideos (url: string) { | ||
150 | const path = '/api/v1/videos' | ||
151 | |||
152 | return request(url) | ||
153 | .get(path) | ||
154 | .query({ sort: 'name', filter: 'local' }) | ||
155 | .set('Accept', 'application/json') | ||
156 | .expect(200) | ||
157 | .expect('Content-Type', /json/) | ||
158 | } | ||
159 | |||
160 | function getMyVideos (url: string, accessToken: string, start: number, count: number, sort?: string) { | ||
161 | const path = '/api/v1/users/me/videos' | ||
162 | |||
163 | const req = request(url) | ||
164 | .get(path) | ||
165 | .query({ start: start }) | ||
166 | .query({ count: count }) | ||
167 | |||
168 | if (sort) req.query({ sort }) | ||
169 | |||
170 | return req.set('Accept', 'application/json') | ||
171 | .set('Authorization', 'Bearer ' + accessToken) | ||
172 | .expect(200) | ||
173 | .expect('Content-Type', /json/) | ||
174 | } | ||
175 | |||
176 | function getAccountVideos ( | ||
177 | url: string, | ||
178 | accessToken: string, | ||
179 | accountName: string, | ||
180 | start: number, | ||
181 | count: number, | ||
182 | sort?: string, | ||
183 | query: { nsfw?: boolean } = {} | ||
184 | ) { | ||
185 | const path = '/api/v1/accounts/' + accountName + '/videos' | ||
186 | |||
187 | return makeGetRequest({ | ||
188 | url, | ||
189 | path, | ||
190 | query: immutableAssign(query, { | ||
191 | start, | ||
192 | count, | ||
193 | sort | ||
194 | }), | ||
195 | token: accessToken, | ||
196 | statusCodeExpected: 200 | ||
197 | }) | ||
198 | } | ||
199 | |||
200 | function getVideoChannelVideos ( | ||
201 | url: string, | ||
202 | accessToken: string, | ||
203 | videoChannelName: string, | ||
204 | start: number, | ||
205 | count: number, | ||
206 | sort?: string, | ||
207 | query: { nsfw?: boolean } = {} | ||
208 | ) { | ||
209 | const path = '/api/v1/video-channels/' + videoChannelName + '/videos' | ||
210 | |||
211 | return makeGetRequest({ | ||
212 | url, | ||
213 | path, | ||
214 | query: immutableAssign(query, { | ||
215 | start, | ||
216 | count, | ||
217 | sort | ||
218 | }), | ||
219 | token: accessToken, | ||
220 | statusCodeExpected: 200 | ||
221 | }) | ||
222 | } | ||
223 | |||
224 | function getVideosListPagination (url: string, start: number, count: number, sort?: string) { | ||
225 | const path = '/api/v1/videos' | ||
226 | |||
227 | const req = request(url) | ||
228 | .get(path) | ||
229 | .query({ start: start }) | ||
230 | .query({ count: count }) | ||
231 | |||
232 | if (sort) req.query({ sort }) | ||
233 | |||
234 | return req.set('Accept', 'application/json') | ||
235 | .expect(200) | ||
236 | .expect('Content-Type', /json/) | ||
237 | } | ||
238 | |||
239 | function getVideosListSort (url: string, sort: string) { | ||
240 | const path = '/api/v1/videos' | ||
241 | |||
242 | return request(url) | ||
243 | .get(path) | ||
244 | .query({ sort: sort }) | ||
245 | .set('Accept', 'application/json') | ||
246 | .expect(200) | ||
247 | .expect('Content-Type', /json/) | ||
248 | } | ||
249 | |||
250 | function getVideosWithFilters (url: string, query: { tagsAllOf: string[], categoryOneOf: number[] | number }) { | ||
251 | const path = '/api/v1/videos' | ||
252 | |||
253 | return request(url) | ||
254 | .get(path) | ||
255 | .query(query) | ||
256 | .set('Accept', 'application/json') | ||
257 | .expect(200) | ||
258 | .expect('Content-Type', /json/) | ||
259 | } | ||
260 | |||
261 | function removeVideo (url: string, token: string, id: number | string, expectedStatus = 204) { | ||
262 | const path = '/api/v1/videos' | ||
263 | |||
264 | return request(url) | ||
265 | .delete(path + '/' + id) | ||
266 | .set('Accept', 'application/json') | ||
267 | .set('Authorization', 'Bearer ' + token) | ||
268 | .expect(expectedStatus) | ||
269 | } | ||
270 | |||
271 | async function checkVideoFilesWereRemoved ( | ||
272 | videoUUID: string, | ||
273 | serverNumber: number, | ||
274 | directories = [ 'videos', 'thumbnails', 'torrents', 'previews', 'captions' ] | ||
275 | ) { | ||
276 | const testDirectory = 'test' + serverNumber | ||
277 | |||
278 | for (const directory of directories) { | ||
279 | const directoryPath = join(root(), testDirectory, directory) | ||
280 | |||
281 | const directoryExists = existsSync(directoryPath) | ||
282 | expect(directoryExists).to.be.true | ||
283 | |||
284 | const files = await readdir(directoryPath) | ||
285 | for (const file of files) { | ||
286 | expect(file).to.not.contain(videoUUID) | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = 200) { | ||
292 | const path = '/api/v1/videos/upload' | ||
293 | let defaultChannelId = '1' | ||
294 | |||
295 | try { | ||
296 | const res = await getMyUserInformation(url, accessToken) | ||
297 | defaultChannelId = res.body.videoChannels[0].id | ||
298 | } catch (e) { /* empty */ } | ||
299 | |||
300 | // Override default attributes | ||
301 | const attributes = Object.assign({ | ||
302 | name: 'my super video', | ||
303 | category: 5, | ||
304 | licence: 4, | ||
305 | language: 'zh', | ||
306 | channelId: defaultChannelId, | ||
307 | nsfw: true, | ||
308 | waitTranscoding: false, | ||
309 | description: 'my super description', | ||
310 | support: 'my super support text', | ||
311 | tags: [ 'tag' ], | ||
312 | privacy: VideoPrivacy.PUBLIC, | ||
313 | commentsEnabled: true, | ||
314 | downloadEnabled: true, | ||
315 | fixture: 'video_short.webm' | ||
316 | }, videoAttributesArg) | ||
317 | |||
318 | const req = request(url) | ||
319 | .post(path) | ||
320 | .set('Accept', 'application/json') | ||
321 | .set('Authorization', 'Bearer ' + accessToken) | ||
322 | .field('name', attributes.name) | ||
323 | .field('nsfw', JSON.stringify(attributes.nsfw)) | ||
324 | .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) | ||
325 | .field('downloadEnabled', JSON.stringify(attributes.downloadEnabled)) | ||
326 | .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding)) | ||
327 | .field('privacy', attributes.privacy.toString()) | ||
328 | .field('channelId', attributes.channelId) | ||
329 | |||
330 | if (attributes.description !== undefined) { | ||
331 | req.field('description', attributes.description) | ||
332 | } | ||
333 | if (attributes.language !== undefined) { | ||
334 | req.field('language', attributes.language.toString()) | ||
335 | } | ||
336 | if (attributes.category !== undefined) { | ||
337 | req.field('category', attributes.category.toString()) | ||
338 | } | ||
339 | if (attributes.licence !== undefined) { | ||
340 | req.field('licence', attributes.licence.toString()) | ||
341 | } | ||
342 | |||
343 | for (let i = 0; i < attributes.tags.length; i++) { | ||
344 | req.field('tags[' + i + ']', attributes.tags[i]) | ||
345 | } | ||
346 | |||
347 | if (attributes.thumbnailfile !== undefined) { | ||
348 | req.attach('thumbnailfile', buildAbsoluteFixturePath(attributes.thumbnailfile)) | ||
349 | } | ||
350 | if (attributes.previewfile !== undefined) { | ||
351 | req.attach('previewfile', buildAbsoluteFixturePath(attributes.previewfile)) | ||
352 | } | ||
353 | |||
354 | if (attributes.scheduleUpdate) { | ||
355 | req.field('scheduleUpdate[updateAt]', attributes.scheduleUpdate.updateAt) | ||
356 | |||
357 | if (attributes.scheduleUpdate.privacy) { | ||
358 | req.field('scheduleUpdate[privacy]', attributes.scheduleUpdate.privacy) | ||
359 | } | ||
360 | } | ||
361 | |||
362 | return req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture)) | ||
363 | .expect(specialStatus) | ||
364 | } | ||
365 | |||
366 | function updateVideo (url: string, accessToken: string, id: number | string, attributes: VideoAttributes, statusCodeExpected = 204) { | ||
367 | const path = '/api/v1/videos/' + id | ||
368 | const body = {} | ||
369 | |||
370 | if (attributes.name) body['name'] = attributes.name | ||
371 | if (attributes.category) body['category'] = attributes.category | ||
372 | if (attributes.licence) body['licence'] = attributes.licence | ||
373 | if (attributes.language) body['language'] = attributes.language | ||
374 | if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw) | ||
375 | if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled) | ||
376 | if (attributes.downloadEnabled !== undefined) body['downloadEnabled'] = JSON.stringify(attributes.downloadEnabled) | ||
377 | if (attributes.description) body['description'] = attributes.description | ||
378 | if (attributes.tags) body['tags'] = attributes.tags | ||
379 | if (attributes.privacy) body['privacy'] = attributes.privacy | ||
380 | if (attributes.channelId) body['channelId'] = attributes.channelId | ||
381 | if (attributes.scheduleUpdate) body['scheduleUpdate'] = attributes.scheduleUpdate | ||
382 | |||
383 | // Upload request | ||
384 | if (attributes.thumbnailfile || attributes.previewfile) { | ||
385 | const attaches: any = {} | ||
386 | if (attributes.thumbnailfile) attaches.thumbnailfile = attributes.thumbnailfile | ||
387 | if (attributes.previewfile) attaches.previewfile = attributes.previewfile | ||
388 | |||
389 | return makeUploadRequest({ | ||
390 | url, | ||
391 | method: 'PUT', | ||
392 | path, | ||
393 | token: accessToken, | ||
394 | fields: body, | ||
395 | attaches, | ||
396 | statusCodeExpected | ||
397 | }) | ||
398 | } | ||
399 | |||
400 | return makePutBodyRequest({ | ||
401 | url, | ||
402 | path, | ||
403 | fields: body, | ||
404 | token: accessToken, | ||
405 | statusCodeExpected | ||
406 | }) | ||
407 | } | ||
408 | |||
409 | function rateVideo (url: string, accessToken: string, id: number, rating: string, specialStatus = 204) { | ||
410 | const path = '/api/v1/videos/' + id + '/rate' | ||
411 | |||
412 | return request(url) | ||
413 | .put(path) | ||
414 | .set('Accept', 'application/json') | ||
415 | .set('Authorization', 'Bearer ' + accessToken) | ||
416 | .send({ rating }) | ||
417 | .expect(specialStatus) | ||
418 | } | ||
419 | |||
420 | function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) { | ||
421 | return new Promise<any>((res, rej) => { | ||
422 | const torrentName = videoUUID + '-' + resolution + '.torrent' | ||
423 | const torrentPath = join(__dirname, '..', '..', '..', '..', 'test' + server.serverNumber, 'torrents', torrentName) | ||
424 | readFile(torrentPath, (err, data) => { | ||
425 | if (err) return rej(err) | ||
426 | |||
427 | return res(parseTorrent(data)) | ||
428 | }) | ||
429 | }) | ||
430 | } | ||
431 | |||
432 | async function completeVideoCheck ( | ||
433 | url: string, | ||
434 | video: any, | ||
435 | attributes: { | ||
436 | name: string | ||
437 | category: number | ||
438 | licence: number | ||
439 | language: string | ||
440 | nsfw: boolean | ||
441 | commentsEnabled: boolean | ||
442 | downloadEnabled: boolean | ||
443 | description: string | ||
444 | publishedAt?: string | ||
445 | support: string | ||
446 | account: { | ||
447 | name: string | ||
448 | host: string | ||
449 | } | ||
450 | isLocal: boolean | ||
451 | tags: string[] | ||
452 | privacy: number | ||
453 | likes?: number | ||
454 | dislikes?: number | ||
455 | duration: number | ||
456 | channel: { | ||
457 | displayName: string | ||
458 | name: string | ||
459 | description | ||
460 | isLocal: boolean | ||
461 | } | ||
462 | fixture: string | ||
463 | files: { | ||
464 | resolution: number | ||
465 | size: number | ||
466 | }[], | ||
467 | thumbnailfile?: string | ||
468 | previewfile?: string | ||
469 | } | ||
470 | ) { | ||
471 | if (!attributes.likes) attributes.likes = 0 | ||
472 | if (!attributes.dislikes) attributes.dislikes = 0 | ||
473 | |||
474 | expect(video.name).to.equal(attributes.name) | ||
475 | expect(video.category.id).to.equal(attributes.category) | ||
476 | expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc') | ||
477 | expect(video.licence.id).to.equal(attributes.licence) | ||
478 | expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown') | ||
479 | expect(video.language.id).to.equal(attributes.language) | ||
480 | expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown') | ||
481 | expect(video.privacy.id).to.deep.equal(attributes.privacy) | ||
482 | expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) | ||
483 | expect(video.nsfw).to.equal(attributes.nsfw) | ||
484 | expect(video.description).to.equal(attributes.description) | ||
485 | expect(video.account.id).to.be.a('number') | ||
486 | expect(video.account.uuid).to.be.a('string') | ||
487 | expect(video.account.host).to.equal(attributes.account.host) | ||
488 | expect(video.account.name).to.equal(attributes.account.name) | ||
489 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
490 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
491 | expect(video.likes).to.equal(attributes.likes) | ||
492 | expect(video.dislikes).to.equal(attributes.dislikes) | ||
493 | expect(video.isLocal).to.equal(attributes.isLocal) | ||
494 | expect(video.duration).to.equal(attributes.duration) | ||
495 | expect(dateIsValid(video.createdAt)).to.be.true | ||
496 | expect(dateIsValid(video.publishedAt)).to.be.true | ||
497 | expect(dateIsValid(video.updatedAt)).to.be.true | ||
498 | |||
499 | if (attributes.publishedAt) { | ||
500 | expect(video.publishedAt).to.equal(attributes.publishedAt) | ||
501 | } | ||
502 | |||
503 | const res = await getVideo(url, video.uuid) | ||
504 | const videoDetails: VideoDetails = res.body | ||
505 | |||
506 | expect(videoDetails.files).to.have.lengthOf(attributes.files.length) | ||
507 | expect(videoDetails.tags).to.deep.equal(attributes.tags) | ||
508 | expect(videoDetails.account.name).to.equal(attributes.account.name) | ||
509 | expect(videoDetails.account.host).to.equal(attributes.account.host) | ||
510 | expect(video.channel.displayName).to.equal(attributes.channel.displayName) | ||
511 | expect(video.channel.name).to.equal(attributes.channel.name) | ||
512 | expect(videoDetails.channel.host).to.equal(attributes.account.host) | ||
513 | expect(videoDetails.channel.isLocal).to.equal(attributes.channel.isLocal) | ||
514 | expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true | ||
515 | expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true | ||
516 | expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) | ||
517 | expect(videoDetails.downloadEnabled).to.equal(attributes.downloadEnabled) | ||
518 | |||
519 | for (const attributeFile of attributes.files) { | ||
520 | const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution) | ||
521 | expect(file).not.to.be.undefined | ||
522 | |||
523 | let extension = extname(attributes.fixture) | ||
524 | // Transcoding enabled on server 2, extension will always be .mp4 | ||
525 | if (attributes.account.host === 'localhost:9002') extension = '.mp4' | ||
526 | |||
527 | const magnetUri = file.magnetUri | ||
528 | expect(file.magnetUri).to.have.lengthOf.above(2) | ||
529 | expect(file.torrentUrl).to.equal(`http://${attributes.account.host}/static/torrents/${videoDetails.uuid}-${file.resolution.id}.torrent`) | ||
530 | expect(file.fileUrl).to.equal(`http://${attributes.account.host}/static/webseed/${videoDetails.uuid}-${file.resolution.id}${extension}`) | ||
531 | expect(file.resolution.id).to.equal(attributeFile.resolution) | ||
532 | expect(file.resolution.label).to.equal(attributeFile.resolution + 'p') | ||
533 | |||
534 | const minSize = attributeFile.size - ((10 * attributeFile.size) / 100) | ||
535 | const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100) | ||
536 | expect(file.size, | ||
537 | 'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')') | ||
538 | .to.be.above(minSize).and.below(maxSize) | ||
539 | |||
540 | { | ||
541 | await testImage(url, attributes.thumbnailfile || attributes.fixture, videoDetails.thumbnailPath) | ||
542 | } | ||
543 | |||
544 | if (attributes.previewfile) { | ||
545 | await testImage(url, attributes.previewfile, videoDetails.previewPath) | ||
546 | } | ||
547 | |||
548 | const torrent = await webtorrentAdd(magnetUri, true) | ||
549 | expect(torrent.files).to.be.an('array') | ||
550 | expect(torrent.files.length).to.equal(1) | ||
551 | expect(torrent.files[0].path).to.exist.and.to.not.equal('') | ||
552 | } | ||
553 | } | ||
554 | |||
555 | // --------------------------------------------------------------------------- | ||
556 | |||
557 | export { | ||
558 | getVideoDescription, | ||
559 | getVideoCategories, | ||
560 | getVideoLicences, | ||
561 | getVideoPrivacies, | ||
562 | getVideoLanguages, | ||
563 | getMyVideos, | ||
564 | getAccountVideos, | ||
565 | getVideoChannelVideos, | ||
566 | getVideo, | ||
567 | getVideoWithToken, | ||
568 | getVideosList, | ||
569 | getVideosListPagination, | ||
570 | getVideosListSort, | ||
571 | removeVideo, | ||
572 | getVideosListWithToken, | ||
573 | uploadVideo, | ||
574 | getVideosWithFilters, | ||
575 | updateVideo, | ||
576 | rateVideo, | ||
577 | viewVideo, | ||
578 | parseTorrentVideo, | ||
579 | getLocalVideos, | ||
580 | completeVideoCheck, | ||
581 | checkVideoFilesWereRemoved | ||
582 | } | ||