diff options
author | Chocobozzz <me@florianbigard.com> | 2023-07-31 14:34:36 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-08-11 15:02:33 +0200 |
commit | 3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch) | |
tree | e4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/tests/api/check-params/video-channel-syncs.ts | |
parent | 04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff) | |
download | PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip |
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge
conflicts, but it's a major step forward:
* Server can be faster at startup because imports() are async and we can
easily lazy import big modules
* Angular doesn't seem to support ES import (with .js extension), so we
had to correctly organize peertube into a monorepo:
* Use yarn workspace feature
* Use typescript reference projects for dependencies
* Shared projects have been moved into "packages", each one is now a
node module (with a dedicated package.json/tsconfig.json)
* server/tools have been moved into apps/ and is now a dedicated app
bundled and published on NPM so users don't have to build peertube
cli tools manually
* server/tests have been moved into packages/ so we don't compile
them every time we want to run the server
* Use isolatedModule option:
* Had to move from const enum to const
(https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums)
* Had to explictely specify "type" imports when used in decorators
* Prefer tsx (that uses esbuild under the hood) instead of ts-node to
load typescript files (tests with mocha or scripts):
* To reduce test complexity as esbuild doesn't support decorator
metadata, we only test server files that do not import server
models
* We still build tests files into js files for a faster CI
* Remove unmaintained peertube CLI import script
* Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/tests/api/check-params/video-channel-syncs.ts')
-rw-r--r-- | server/tests/api/check-params/video-channel-syncs.ts | 318 |
1 files changed, 0 insertions, 318 deletions
diff --git a/server/tests/api/check-params/video-channel-syncs.ts b/server/tests/api/check-params/video-channel-syncs.ts deleted file mode 100644 index bcd8984df..000000000 --- a/server/tests/api/check-params/video-channel-syncs.ts +++ /dev/null | |||
@@ -1,318 +0,0 @@ | |||
1 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared' | ||
2 | import { HttpStatusCode, VideoChannelSyncCreate } from '@shared/models' | ||
3 | import { | ||
4 | ChannelSyncsCommand, | ||
5 | createSingleServer, | ||
6 | makePostBodyRequest, | ||
7 | PeerTubeServer, | ||
8 | setAccessTokensToServers, | ||
9 | setDefaultVideoChannel | ||
10 | } from '@shared/server-commands' | ||
11 | |||
12 | describe('Test video channel sync API validator', () => { | ||
13 | const path = '/api/v1/video-channel-syncs' | ||
14 | let server: PeerTubeServer | ||
15 | let command: ChannelSyncsCommand | ||
16 | let rootChannelId: number | ||
17 | let rootChannelSyncId: number | ||
18 | const userInfo = { | ||
19 | accessToken: '', | ||
20 | username: 'user1', | ||
21 | id: -1, | ||
22 | channelId: -1, | ||
23 | syncId: -1 | ||
24 | } | ||
25 | |||
26 | async function withChannelSyncDisabled<T> (callback: () => Promise<T>): Promise<void> { | ||
27 | try { | ||
28 | await server.config.disableChannelSync() | ||
29 | await callback() | ||
30 | } finally { | ||
31 | await server.config.enableChannelSync() | ||
32 | } | ||
33 | } | ||
34 | |||
35 | async function withMaxSyncsPerUser<T> (maxSync: number, callback: () => Promise<T>): Promise<void> { | ||
36 | const origConfig = await server.config.getCustomConfig() | ||
37 | |||
38 | await server.config.updateExistingSubConfig({ | ||
39 | newConfig: { | ||
40 | import: { | ||
41 | videoChannelSynchronization: { | ||
42 | maxPerUser: maxSync | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | }) | ||
47 | |||
48 | try { | ||
49 | await callback() | ||
50 | } finally { | ||
51 | await server.config.updateCustomConfig({ newCustomConfig: origConfig }) | ||
52 | } | ||
53 | } | ||
54 | |||
55 | before(async function () { | ||
56 | this.timeout(30_000) | ||
57 | |||
58 | server = await createSingleServer(1) | ||
59 | |||
60 | await setAccessTokensToServers([ server ]) | ||
61 | await setDefaultVideoChannel([ server ]) | ||
62 | |||
63 | command = server.channelSyncs | ||
64 | |||
65 | rootChannelId = server.store.channel.id | ||
66 | |||
67 | { | ||
68 | userInfo.accessToken = await server.users.generateUserAndToken(userInfo.username) | ||
69 | |||
70 | const { videoChannels, id: userId } = await server.users.getMyInfo({ token: userInfo.accessToken }) | ||
71 | userInfo.id = userId | ||
72 | userInfo.channelId = videoChannels[0].id | ||
73 | } | ||
74 | |||
75 | await server.config.enableChannelSync() | ||
76 | }) | ||
77 | |||
78 | describe('When creating a sync', function () { | ||
79 | let baseCorrectParams: VideoChannelSyncCreate | ||
80 | |||
81 | before(function () { | ||
82 | baseCorrectParams = { | ||
83 | externalChannelUrl: FIXTURE_URLS.youtubeChannel, | ||
84 | videoChannelId: rootChannelId | ||
85 | } | ||
86 | }) | ||
87 | |||
88 | it('Should fail when sync is disabled', async function () { | ||
89 | await withChannelSyncDisabled(async () => { | ||
90 | await command.create({ | ||
91 | token: server.accessToken, | ||
92 | attributes: baseCorrectParams, | ||
93 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
94 | }) | ||
95 | }) | ||
96 | }) | ||
97 | |||
98 | it('Should fail with nothing', async function () { | ||
99 | const fields = {} | ||
100 | await makePostBodyRequest({ | ||
101 | url: server.url, | ||
102 | path, | ||
103 | token: server.accessToken, | ||
104 | fields, | ||
105 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
106 | }) | ||
107 | }) | ||
108 | |||
109 | it('Should fail with no authentication', async function () { | ||
110 | await command.create({ | ||
111 | token: null, | ||
112 | attributes: baseCorrectParams, | ||
113 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | ||
114 | }) | ||
115 | }) | ||
116 | |||
117 | it('Should fail without a target url', async function () { | ||
118 | const attributes: VideoChannelSyncCreate = { | ||
119 | ...baseCorrectParams, | ||
120 | externalChannelUrl: null | ||
121 | } | ||
122 | await command.create({ | ||
123 | token: server.accessToken, | ||
124 | attributes, | ||
125 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
126 | }) | ||
127 | }) | ||
128 | |||
129 | it('Should fail without a channelId', async function () { | ||
130 | const attributes: VideoChannelSyncCreate = { | ||
131 | ...baseCorrectParams, | ||
132 | videoChannelId: null | ||
133 | } | ||
134 | await command.create({ | ||
135 | token: server.accessToken, | ||
136 | attributes, | ||
137 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
138 | }) | ||
139 | }) | ||
140 | |||
141 | it('Should fail with a channelId refering nothing', async function () { | ||
142 | const attributes: VideoChannelSyncCreate = { | ||
143 | ...baseCorrectParams, | ||
144 | videoChannelId: 42 | ||
145 | } | ||
146 | await command.create({ | ||
147 | token: server.accessToken, | ||
148 | attributes, | ||
149 | expectedStatus: HttpStatusCode.NOT_FOUND_404 | ||
150 | }) | ||
151 | }) | ||
152 | |||
153 | it('Should fail to create a sync when the user does not own the channel', async function () { | ||
154 | await command.create({ | ||
155 | token: userInfo.accessToken, | ||
156 | attributes: baseCorrectParams, | ||
157 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
158 | }) | ||
159 | }) | ||
160 | |||
161 | it('Should succeed to create a sync with root and for another user\'s channel', async function () { | ||
162 | const { videoChannelSync } = await command.create({ | ||
163 | token: server.accessToken, | ||
164 | attributes: { | ||
165 | ...baseCorrectParams, | ||
166 | videoChannelId: userInfo.channelId | ||
167 | }, | ||
168 | expectedStatus: HttpStatusCode.OK_200 | ||
169 | }) | ||
170 | userInfo.syncId = videoChannelSync.id | ||
171 | }) | ||
172 | |||
173 | it('Should succeed with the correct parameters', async function () { | ||
174 | const { videoChannelSync } = await command.create({ | ||
175 | token: server.accessToken, | ||
176 | attributes: baseCorrectParams, | ||
177 | expectedStatus: HttpStatusCode.OK_200 | ||
178 | }) | ||
179 | rootChannelSyncId = videoChannelSync.id | ||
180 | }) | ||
181 | |||
182 | it('Should fail when the user exceeds allowed number of synchronizations', async function () { | ||
183 | await withMaxSyncsPerUser(1, async () => { | ||
184 | await command.create({ | ||
185 | token: server.accessToken, | ||
186 | attributes: { | ||
187 | ...baseCorrectParams, | ||
188 | videoChannelId: userInfo.channelId | ||
189 | }, | ||
190 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
191 | }) | ||
192 | }) | ||
193 | }) | ||
194 | }) | ||
195 | |||
196 | describe('When listing my channel syncs', function () { | ||
197 | const myPath = '/api/v1/accounts/root/video-channel-syncs' | ||
198 | |||
199 | it('Should fail with a bad start pagination', async function () { | ||
200 | await checkBadStartPagination(server.url, myPath, server.accessToken) | ||
201 | }) | ||
202 | |||
203 | it('Should fail with a bad count pagination', async function () { | ||
204 | await checkBadCountPagination(server.url, myPath, server.accessToken) | ||
205 | }) | ||
206 | |||
207 | it('Should fail with an incorrect sort', async function () { | ||
208 | await checkBadSortPagination(server.url, myPath, server.accessToken) | ||
209 | }) | ||
210 | |||
211 | it('Should succeed with the correct parameters', async function () { | ||
212 | await command.listByAccount({ | ||
213 | accountName: 'root', | ||
214 | token: server.accessToken, | ||
215 | expectedStatus: HttpStatusCode.OK_200 | ||
216 | }) | ||
217 | }) | ||
218 | |||
219 | it('Should fail with no authentication', async function () { | ||
220 | await command.listByAccount({ | ||
221 | accountName: 'root', | ||
222 | token: null, | ||
223 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | ||
224 | }) | ||
225 | }) | ||
226 | |||
227 | it('Should fail when a simple user lists another user\'s synchronizations', async function () { | ||
228 | await command.listByAccount({ | ||
229 | accountName: 'root', | ||
230 | token: userInfo.accessToken, | ||
231 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
232 | }) | ||
233 | }) | ||
234 | |||
235 | it('Should succeed when root lists another user\'s synchronizations', async function () { | ||
236 | await command.listByAccount({ | ||
237 | accountName: userInfo.username, | ||
238 | token: server.accessToken, | ||
239 | expectedStatus: HttpStatusCode.OK_200 | ||
240 | }) | ||
241 | }) | ||
242 | |||
243 | it('Should succeed even with synchronization disabled', async function () { | ||
244 | await withChannelSyncDisabled(async function () { | ||
245 | await command.listByAccount({ | ||
246 | accountName: 'root', | ||
247 | token: server.accessToken, | ||
248 | expectedStatus: HttpStatusCode.OK_200 | ||
249 | }) | ||
250 | }) | ||
251 | }) | ||
252 | }) | ||
253 | |||
254 | describe('When triggering deletion', function () { | ||
255 | it('should fail with no authentication', async function () { | ||
256 | await command.delete({ | ||
257 | channelSyncId: userInfo.syncId, | ||
258 | token: null, | ||
259 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | ||
260 | }) | ||
261 | }) | ||
262 | |||
263 | it('Should fail when channelSyncId does not refer to any sync', async function () { | ||
264 | await command.delete({ | ||
265 | channelSyncId: 42, | ||
266 | token: server.accessToken, | ||
267 | expectedStatus: HttpStatusCode.NOT_FOUND_404 | ||
268 | }) | ||
269 | }) | ||
270 | |||
271 | it('Should fail when sync is not owned by the user', async function () { | ||
272 | await command.delete({ | ||
273 | channelSyncId: rootChannelSyncId, | ||
274 | token: userInfo.accessToken, | ||
275 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
276 | }) | ||
277 | }) | ||
278 | |||
279 | it('Should succeed when root delete a sync they do not own', async function () { | ||
280 | await command.delete({ | ||
281 | channelSyncId: userInfo.syncId, | ||
282 | token: server.accessToken, | ||
283 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
284 | }) | ||
285 | }) | ||
286 | |||
287 | it('should succeed when user delete a sync they own', async function () { | ||
288 | const { videoChannelSync } = await command.create({ | ||
289 | attributes: { | ||
290 | externalChannelUrl: FIXTURE_URLS.youtubeChannel, | ||
291 | videoChannelId: userInfo.channelId | ||
292 | }, | ||
293 | token: server.accessToken, | ||
294 | expectedStatus: HttpStatusCode.OK_200 | ||
295 | }) | ||
296 | |||
297 | await command.delete({ | ||
298 | channelSyncId: videoChannelSync.id, | ||
299 | token: server.accessToken, | ||
300 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
301 | }) | ||
302 | }) | ||
303 | |||
304 | it('Should succeed even when synchronization is disabled', async function () { | ||
305 | await withChannelSyncDisabled(async function () { | ||
306 | await command.delete({ | ||
307 | channelSyncId: rootChannelSyncId, | ||
308 | token: server.accessToken, | ||
309 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
310 | }) | ||
311 | }) | ||
312 | }) | ||
313 | }) | ||
314 | |||
315 | after(async function () { | ||
316 | await server?.kill() | ||
317 | }) | ||
318 | }) | ||