From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001
From: Chocobozzz
Date: Mon, 31 Jul 2023 14:34:36 +0200
Subject: 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)
---
server/tests/api/activitypub/cleaner.ts | 342 ------
server/tests/api/activitypub/client.ts | 136 ---
server/tests/api/activitypub/fetch.ts | 82 --
server/tests/api/activitypub/helpers.ts | 167 ---
server/tests/api/activitypub/index.ts | 6 -
server/tests/api/activitypub/refresher.ts | 157 ---
server/tests/api/activitypub/security.ts | 321 ------
server/tests/api/check-params/abuses.ts | 438 -------
server/tests/api/check-params/accounts.ts | 43 -
server/tests/api/check-params/blocklist.ts | 556 ---------
server/tests/api/check-params/bulk.ts | 80 --
.../api/check-params/channel-import-videos.ts | 209 ----
server/tests/api/check-params/config.ts | 428 -------
server/tests/api/check-params/contact-form.ts | 86 --
server/tests/api/check-params/custom-pages.ts | 79 --
server/tests/api/check-params/debug.ts | 61 -
server/tests/api/check-params/follows.ts | 369 ------
server/tests/api/check-params/index.ts | 45 -
server/tests/api/check-params/jobs.ts | 125 --
server/tests/api/check-params/live.ts | 589 ----------
server/tests/api/check-params/logs.ts | 157 ---
server/tests/api/check-params/metrics.ts | 208 ----
server/tests/api/check-params/my-user.ts | 491 --------
server/tests/api/check-params/plugins.ts | 490 --------
server/tests/api/check-params/redundancy.ts | 240 ----
server/tests/api/check-params/registrations.ts | 446 --------
server/tests/api/check-params/runners.ts | 910 ---------------
server/tests/api/check-params/search.ts | 272 -----
server/tests/api/check-params/services.ts | 195 ----
server/tests/api/check-params/transcoding.ts | 112 --
server/tests/api/check-params/two-factor.ts | 288 -----
server/tests/api/check-params/upload-quota.ts | 134 ---
.../tests/api/check-params/user-notifications.ts | 290 -----
.../tests/api/check-params/user-subscriptions.ts | 298 -----
server/tests/api/check-params/users-admin.ts | 456 --------
server/tests/api/check-params/users-emails.ts | 116 --
server/tests/api/check-params/video-blacklist.ts | 292 -----
server/tests/api/check-params/video-captions.ts | 307 -----
.../tests/api/check-params/video-channel-syncs.ts | 318 ------
server/tests/api/check-params/video-channels.ts | 378 ------
server/tests/api/check-params/video-comments.ts | 484 --------
server/tests/api/check-params/video-files.ts | 195 ----
server/tests/api/check-params/video-imports.ts | 431 -------
server/tests/api/check-params/video-passwords.ts | 609 ----------
server/tests/api/check-params/video-playlists.ts | 695 -----------
server/tests/api/check-params/video-source.ts | 154 ---
server/tests/api/check-params/video-storyboards.ts | 45 -
server/tests/api/check-params/video-studio.ts | 388 -------
server/tests/api/check-params/video-token.ts | 70 --
.../api/check-params/videos-common-filters.ts | 163 ---
server/tests/api/check-params/videos-history.ts | 145 ---
server/tests/api/check-params/videos-overviews.ts | 31 -
server/tests/api/check-params/videos.ts | 881 --------------
server/tests/api/check-params/views.ts | 227 ----
server/tests/api/index.ts | 13 -
server/tests/api/live/index.ts | 7 -
server/tests/api/live/live-constraints.ts | 237 ----
server/tests/api/live/live-fast-restream.ts | 153 ---
server/tests/api/live/live-permanent.ts | 204 ----
server/tests/api/live/live-rtmps.ts | 143 ---
server/tests/api/live/live-save-replay.ts | 570 ---------
server/tests/api/live/live-socket-messages.ts | 186 ---
server/tests/api/live/live.ts | 764 -------------
server/tests/api/moderation/abuses.ts | 887 --------------
.../tests/api/moderation/blocklist-notification.ts | 231 ----
server/tests/api/moderation/blocklist.ts | 902 ---------------
server/tests/api/moderation/index.ts | 4 -
server/tests/api/moderation/video-blacklist.ts | 414 -------
.../tests/api/notifications/admin-notifications.ts | 159 ---
.../api/notifications/comments-notifications.ts | 305 -----
server/tests/api/notifications/index.ts | 6 -
.../api/notifications/moderation-notifications.ts | 609 ----------
.../tests/api/notifications/notifications-api.ts | 206 ----
.../notifications/registrations-notifications.ts | 88 --
.../tests/api/notifications/user-notifications.ts | 574 ----------
server/tests/api/object-storage/index.ts | 4 -
server/tests/api/object-storage/live.ts | 311 -----
server/tests/api/object-storage/video-imports.ts | 111 --
.../object-storage/video-static-file-privacy.ts | 570 ---------
server/tests/api/object-storage/videos.ts | 438 -------
server/tests/api/redundancy/index.ts | 3 -
server/tests/api/redundancy/manage-redundancy.ts | 324 ------
.../tests/api/redundancy/redundancy-constraints.ts | 191 ----
server/tests/api/redundancy/redundancy.ts | 742 ------------
server/tests/api/runners/index.ts | 5 -
server/tests/api/runners/runner-common.ts | 743 ------------
.../tests/api/runners/runner-live-transcoding.ts | 330 ------
server/tests/api/runners/runner-socket.ts | 120 --
.../tests/api/runners/runner-studio-transcoding.ts | 168 ---
server/tests/api/runners/runner-vod-transcoding.ts | 545 ---------
server/tests/api/search/index.ts | 7 -
.../search/search-activitypub-video-channels.ts | 255 -----
.../search/search-activitypub-video-playlists.ts | 214 ----
.../tests/api/search/search-activitypub-videos.ts | 196 ----
server/tests/api/search/search-channels.ts | 159 ---
server/tests/api/search/search-index.ts | 432 -------
server/tests/api/search/search-playlists.ts | 180 ---
server/tests/api/search/search-videos.ts | 568 ---------
server/tests/api/server/auto-follows.ts | 189 ---
server/tests/api/server/bulk.ts | 185 ---
server/tests/api/server/config-defaults.ts | 288 -----
server/tests/api/server/config.ts | 645 -----------
server/tests/api/server/contact-form.ts | 101 --
server/tests/api/server/email.ts | 371 ------
server/tests/api/server/follow-constraints.ts | 321 ------
server/tests/api/server/follows-moderation.ts | 364 ------
server/tests/api/server/follows.ts | 641 -----------
server/tests/api/server/handle-down.ts | 338 ------
server/tests/api/server/homepage.ts | 81 --
server/tests/api/server/index.ts | 22 -
server/tests/api/server/jobs.ts | 128 ---
server/tests/api/server/logs.ts | 265 -----
server/tests/api/server/no-client.ts | 24 -
server/tests/api/server/open-telemetry.ts | 186 ---
server/tests/api/server/plugins.ts | 409 -------
server/tests/api/server/proxy.ts | 171 ---
server/tests/api/server/reverse-proxy.ts | 156 ---
server/tests/api/server/services.ts | 137 ---
server/tests/api/server/slow-follows.ts | 85 --
server/tests/api/server/stats.ts | 279 -----
server/tests/api/server/tracker.ts | 104 --
server/tests/api/transcoding/audio-only.ts | 104 --
server/tests/api/transcoding/create-transcoding.ts | 266 -----
server/tests/api/transcoding/hls.ts | 175 ---
server/tests/api/transcoding/index.ts | 6 -
server/tests/api/transcoding/transcoder.ts | 800 -------------
.../api/transcoding/update-while-transcoding.ts | 160 ---
server/tests/api/transcoding/video-studio.ts | 377 ------
server/tests/api/users/index.ts | 8 -
server/tests/api/users/oauth.ts | 197 ----
server/tests/api/users/registrations.ts | 415 -------
server/tests/api/users/two-factor.ts | 200 ----
server/tests/api/users/user-subscriptions.ts | 614 ----------
server/tests/api/users/user-videos.ts | 219 ----
server/tests/api/users/users-email-verification.ts | 165 ---
server/tests/api/users/users-multiple-servers.ts | 216 ----
server/tests/api/users/users.ts | 529 ---------
server/tests/api/videos/channel-import-videos.ts | 161 ---
server/tests/api/videos/index.ts | 23 -
server/tests/api/videos/multiple-servers.ts | 1099 ------------------
server/tests/api/videos/resumable-upload.ts | 310 -----
server/tests/api/videos/single-server.ts | 460 --------
server/tests/api/videos/video-captions.ts | 188 ---
server/tests/api/videos/video-change-ownership.ts | 314 -----
server/tests/api/videos/video-channel-syncs.ts | 320 ------
server/tests/api/videos/video-channels.ts | 555 ---------
server/tests/api/videos/video-comments.ts | 335 ------
server/tests/api/videos/video-description.ts | 103 --
server/tests/api/videos/video-files.ts | 202 ----
server/tests/api/videos/video-imports.ts | 631 ----------
server/tests/api/videos/video-nsfw.ts | 227 ----
server/tests/api/videos/video-passwords.ts | 97 --
.../tests/api/videos/video-playlist-thumbnails.ts | 234 ----
server/tests/api/videos/video-playlists.ts | 1208 --------------------
server/tests/api/videos/video-privacy.ts | 287 -----
server/tests/api/videos/video-schedule-update.ts | 155 ---
server/tests/api/videos/video-source.ts | 447 --------
.../tests/api/videos/video-static-file-privacy.ts | 600 ----------
server/tests/api/videos/video-storyboard.ts | 213 ----
server/tests/api/videos/videos-common-filters.ts | 489 --------
server/tests/api/videos/videos-history.ts | 224 ----
server/tests/api/videos/videos-overview.ts | 129 ---
server/tests/api/views/index.ts | 5 -
server/tests/api/views/video-views-counter.ts | 153 ---
.../tests/api/views/video-views-overall-stats.ts | 368 ------
.../tests/api/views/video-views-retention-stats.ts | 53 -
.../tests/api/views/video-views-timeserie-stats.ts | 253 ----
server/tests/api/views/videos-views-cleaner.ts | 98 --
server/tests/cli/create-generate-storyboard-job.ts | 120 --
server/tests/cli/create-import-video-file-job.ts | 168 ---
server/tests/cli/create-move-video-storage-job.ts | 124 --
server/tests/cli/index.ts | 10 -
server/tests/cli/peertube.ts | 331 ------
server/tests/cli/plugins.ts | 76 --
server/tests/cli/prune-storage.ts | 223 ----
server/tests/cli/regenerate-thumbnails.ts | 122 --
server/tests/cli/reset-password.ts | 26 -
server/tests/cli/update-host.ts | 134 ---
server/tests/client.ts | 556 ---------
server/tests/external-plugins/akismet.ts | 160 ---
server/tests/external-plugins/auth-ldap.ts | 117 --
server/tests/external-plugins/auto-block-videos.ts | 167 ---
server/tests/external-plugins/auto-mute.ts | 216 ----
server/tests/external-plugins/index.ts | 4 -
server/tests/feeds/feeds.ts | 695 -----------
server/tests/feeds/index.ts | 1 -
server/tests/fixtures/60fps_720p_small.mp4 | Bin 276786 -> 0 bytes
.../ap-json/mastodon/bad-body-http-signature.json | 93 --
.../ap-json/mastodon/bad-http-signature.json | 93 --
.../fixtures/ap-json/mastodon/bad-public-key.json | 3 -
.../ap-json/mastodon/create-bad-signature.json | 81 --
server/tests/fixtures/ap-json/mastodon/create.json | 81 --
.../fixtures/ap-json/mastodon/http-signature.json | 93 --
.../fixtures/ap-json/mastodon/public-key.json | 3 -
.../ap-json/peertube/announce-without-context.json | 13 -
.../fixtures/ap-json/peertube/invalid-keys.json | 6 -
server/tests/fixtures/ap-json/peertube/keys.json | 4 -
server/tests/fixtures/avatar-big.png | Bin 146585 -> 0 bytes
server/tests/fixtures/avatar-resized-120x120.gif | Bin 88318 -> 0 bytes
server/tests/fixtures/avatar-resized-120x120.png | Bin 1727 -> 0 bytes
server/tests/fixtures/avatar-resized-48x48.gif | Bin 20462 -> 0 bytes
server/tests/fixtures/avatar-resized-48x48.png | Bin 727 -> 0 bytes
server/tests/fixtures/avatar.gif | Bin 46917 -> 0 bytes
server/tests/fixtures/avatar.png | Bin 1674 -> 0 bytes
server/tests/fixtures/avatar2-resized-120x120.png | Bin 1725 -> 0 bytes
server/tests/fixtures/avatar2-resized-48x48.png | Bin 760 -> 0 bytes
server/tests/fixtures/avatar2.png | Bin 4850 -> 0 bytes
server/tests/fixtures/banner-resized.jpg | Bin 59947 -> 0 bytes
server/tests/fixtures/banner.jpg | Bin 31648 -> 0 bytes
server/tests/fixtures/custom-preview-big.png | Bin 536513 -> 0 bytes
server/tests/fixtures/custom-preview.jpg | Bin 14146 -> 0 bytes
server/tests/fixtures/custom-thumbnail-big.jpg | Bin 20379 -> 0 bytes
server/tests/fixtures/custom-thumbnail.jpg | Bin 6898 -> 0 bytes
server/tests/fixtures/custom-thumbnail.png | Bin 18070 -> 0 bytes
server/tests/fixtures/exif.jpg | Bin 10877 -> 0 bytes
server/tests/fixtures/exif.png | Bin 21059 -> 0 bytes
server/tests/fixtures/live/0-000067.ts | Bin 270532 -> 0 bytes
server/tests/fixtures/live/0-000068.ts | Bin 181420 -> 0 bytes
server/tests/fixtures/live/0-000069.ts | Bin 345732 -> 0 bytes
server/tests/fixtures/live/0-000070.ts | Bin 282376 -> 0 bytes
server/tests/fixtures/live/0.m3u8 | 14 -
server/tests/fixtures/live/1-000067.ts | Bin 620024 -> 0 bytes
server/tests/fixtures/live/1-000068.ts | Bin 382392 -> 0 bytes
server/tests/fixtures/live/1-000069.ts | Bin 712332 -> 0 bytes
server/tests/fixtures/live/1-000070.ts | Bin 608556 -> 0 bytes
server/tests/fixtures/live/1.m3u8 | 14 -
server/tests/fixtures/live/master.m3u8 | 8 -
server/tests/fixtures/low-bitrate.mp4 | Bin 43850 -> 0 bytes
.../fixtures/peertube-plugin-test-broken/main.js | 12 -
.../peertube-plugin-test-broken/package.json | 20 -
.../peertube-plugin-test-external-auth-one/main.js | 85 --
.../package.json | 20 -
.../main.js | 53 -
.../package.json | 20 -
.../peertube-plugin-test-external-auth-two/main.js | 95 --
.../package.json | 20 -
.../languages/fr.json | 3 -
.../languages/it.json | 3 -
.../main.js | 21 -
.../package.json | 23 -
.../fixtures/peertube-plugin-test-five/main.js | 23 -
.../peertube-plugin-test-five/package.json | 20 -
.../fixtures/peertube-plugin-test-four/main.js | 201 ----
.../peertube-plugin-test-four/package.json | 20 -
.../peertube-plugin-test-id-pass-auth-one/main.js | 69 --
.../package.json | 20 -
.../main.js | 106 --
.../package.json | 20 -
.../peertube-plugin-test-id-pass-auth-two/main.js | 65 --
.../package.json | 20 -
.../fixtures/peertube-plugin-test-native/main.js | 21 -
.../peertube-plugin-test-native/package.json | 23 -
.../main.js | 82 --
.../package.json | 19 -
.../fixtures/peertube-plugin-test-six/main.js | 46 -
.../fixtures/peertube-plugin-test-six/package.json | 20 -
.../peertube-plugin-test-transcoding-one/main.js | 92 --
.../package.json | 20 -
.../peertube-plugin-test-transcoding-two/main.js | 38 -
.../package.json | 20 -
.../fixtures/peertube-plugin-test-unloading/lib.js | 2 -
.../peertube-plugin-test-unloading/main.js | 14 -
.../peertube-plugin-test-unloading/package.json | 20 -
.../peertube-plugin-test-video-constants/main.js | 46 -
.../package.json | 20 -
.../peertube-plugin-test-websocket/main.js | 36 -
.../peertube-plugin-test-websocket/package.json | 20 -
.../peertube-plugin-test/languages/fr.json | 3 -
server/tests/fixtures/peertube-plugin-test/main.js | 477 --------
.../fixtures/peertube-plugin-test/package.json | 22 -
server/tests/fixtures/rtmps.cert | 21 -
server/tests/fixtures/rtmps.key | 28 -
server/tests/fixtures/sample.ogg | Bin 105243 -> 0 bytes
server/tests/fixtures/subtitle-bad.txt | 11 -
server/tests/fixtures/subtitle-good.srt | 11 -
server/tests/fixtures/subtitle-good1.vtt | 8 -
server/tests/fixtures/subtitle-good2.vtt | 8 -
server/tests/fixtures/thumbnail-playlist.jpg | Bin 5040 -> 0 bytes
server/tests/fixtures/video-720p.torrent | Bin 2644 -> 0 bytes
server/tests/fixtures/video_import_preview.jpg | Bin 9551 -> 0 bytes
.../tests/fixtures/video_import_preview_yt_dlp.jpg | Bin 15844 -> 0 bytes
server/tests/fixtures/video_import_thumbnail.jpg | Bin 10980 -> 0 bytes
.../fixtures/video_import_thumbnail_yt_dlp.jpg | Bin 10676 -> 0 bytes
server/tests/fixtures/video_short.avi | Bin 584656 -> 0 bytes
server/tests/fixtures/video_short.mkv | Bin 40642 -> 0 bytes
server/tests/fixtures/video_short.mp4 | Bin 38783 -> 0 bytes
server/tests/fixtures/video_short.mp4.jpg | Bin 5028 -> 0 bytes
server/tests/fixtures/video_short.ogv | Bin 140849 -> 0 bytes
server/tests/fixtures/video_short.ogv.jpg | Bin 5023 -> 0 bytes
server/tests/fixtures/video_short.webm | Bin 218910 -> 0 bytes
server/tests/fixtures/video_short.webm.jpg | Bin 5028 -> 0 bytes
.../tests/fixtures/video_short1-preview.webm.jpg | Bin 31188 -> 0 bytes
server/tests/fixtures/video_short1.webm | Bin 572456 -> 0 bytes
server/tests/fixtures/video_short1.webm.jpg | Bin 6334 -> 0 bytes
server/tests/fixtures/video_short2.webm | Bin 942961 -> 0 bytes
server/tests/fixtures/video_short2.webm.jpg | Bin 6607 -> 0 bytes
server/tests/fixtures/video_short3.webm | Bin 292677 -> 0 bytes
server/tests/fixtures/video_short3.webm.jpg | Bin 5674 -> 0 bytes
server/tests/fixtures/video_short_0p.mp4 | Bin 3051 -> 0 bytes
server/tests/fixtures/video_short_144p.m3u8 | 13 -
server/tests/fixtures/video_short_144p.mp4 | Bin 15634 -> 0 bytes
server/tests/fixtures/video_short_240p.m3u8 | 13 -
server/tests/fixtures/video_short_240p.mp4 | Bin 23084 -> 0 bytes
server/tests/fixtures/video_short_360p.m3u8 | 13 -
server/tests/fixtures/video_short_360p.mp4 | Bin 30620 -> 0 bytes
server/tests/fixtures/video_short_480.webm | Bin 69217 -> 0 bytes
server/tests/fixtures/video_short_480p.m3u8 | 13 -
server/tests/fixtures/video_short_480p.mp4 | Bin 39881 -> 0 bytes
server/tests/fixtures/video_short_4k.mp4 | Bin 618949 -> 0 bytes
server/tests/fixtures/video_short_720p.m3u8 | 13 -
server/tests/fixtures/video_short_720p.mp4 | Bin 59109 -> 0 bytes
server/tests/fixtures/video_short_fake.webm | 1 -
server/tests/fixtures/video_short_mp3_256k.mp4 | Bin 194985 -> 0 bytes
server/tests/fixtures/video_short_no_audio.mp4 | Bin 34259 -> 0 bytes
server/tests/fixtures/video_very_long_10p.mp4 | Bin 185338 -> 0 bytes
server/tests/fixtures/video_very_short_240p.mp4 | Bin 9352 -> 0 bytes
server/tests/helpers/comment-model.ts | 24 -
server/tests/helpers/core-utils.ts | 150 ---
server/tests/helpers/crypto.ts | 33 -
server/tests/helpers/dns.ts | 16 -
server/tests/helpers/image.ts | 96 --
server/tests/helpers/index.ts | 9 -
server/tests/helpers/markdown.ts | 39 -
server/tests/helpers/request.ts | 62 -
server/tests/helpers/validator.ts | 32 -
server/tests/helpers/version.ts | 36 -
server/tests/index.ts | 10 -
server/tests/lib/index.ts | 1 -
.../tests/lib/video-constant-registry-factory.ts | 154 ---
server/tests/misc-endpoints.ts | 237 ----
server/tests/peertube-runner/client-cli.ts | 70 --
server/tests/peertube-runner/index.ts | 4 -
server/tests/peertube-runner/live-transcoding.ts | 201 ----
server/tests/peertube-runner/studio-transcoding.ts | 124 --
server/tests/peertube-runner/vod-transcoding.ts | 350 ------
server/tests/plugins/action-hooks.ts | 298 -----
server/tests/plugins/external-auth.ts | 436 -------
server/tests/plugins/filter-hooks.ts | 909 ---------------
server/tests/plugins/html-injection.ts | 73 --
server/tests/plugins/id-and-pass-auth.ts | 242 ----
server/tests/plugins/index.ts | 13 -
server/tests/plugins/plugin-helpers.ts | 383 -------
server/tests/plugins/plugin-router.ts | 105 --
server/tests/plugins/plugin-storage.ts | 94 --
server/tests/plugins/plugin-transcoding.ts | 279 -----
server/tests/plugins/plugin-unloading.ts | 75 --
server/tests/plugins/plugin-websocket.ts | 70 --
server/tests/plugins/translations.ts | 74 --
server/tests/plugins/video-constants.ts | 180 ---
server/tests/shared/actors.ts | 69 --
server/tests/shared/captions.ts | 21 -
server/tests/shared/checks.ts | 174 ---
server/tests/shared/directories.ts | 43 -
server/tests/shared/generate.ts | 74 --
server/tests/shared/index.ts | 19 -
server/tests/shared/live.ts | 185 ---
server/tests/shared/mock-servers/index.ts | 8 -
server/tests/shared/mock-servers/mock-429.ts | 33 -
server/tests/shared/mock-servers/mock-email.ts | 61 -
server/tests/shared/mock-servers/mock-http.ts | 23 -
.../shared/mock-servers/mock-instances-index.ts | 46 -
.../mock-servers/mock-joinpeertube-versions.ts | 34 -
.../shared/mock-servers/mock-object-storage.ts | 41 -
.../shared/mock-servers/mock-plugin-blocklist.ts | 36 -
server/tests/shared/mock-servers/mock-proxy.ts | 24 -
server/tests/shared/mock-servers/shared.ts | 33 -
server/tests/shared/notifications.ts | 889 --------------
server/tests/shared/peertube-runner-process.ts | 98 --
server/tests/shared/plugins.ts | 18 -
server/tests/shared/requests.ts | 12 -
server/tests/shared/sql-command.ts | 150 ---
server/tests/shared/streaming-playlists.ts | 296 -----
server/tests/shared/tests.ts | 40 -
server/tests/shared/tracker.ts | 27 -
server/tests/shared/video-playlists.ts | 22 -
server/tests/shared/videos.ts | 315 -----
server/tests/shared/views.ts | 93 --
server/tests/shared/webtorrent.ts | 58 -
378 files changed, 62105 deletions(-)
delete mode 100644 server/tests/api/activitypub/cleaner.ts
delete mode 100644 server/tests/api/activitypub/client.ts
delete mode 100644 server/tests/api/activitypub/fetch.ts
delete mode 100644 server/tests/api/activitypub/helpers.ts
delete mode 100644 server/tests/api/activitypub/index.ts
delete mode 100644 server/tests/api/activitypub/refresher.ts
delete mode 100644 server/tests/api/activitypub/security.ts
delete mode 100644 server/tests/api/check-params/abuses.ts
delete mode 100644 server/tests/api/check-params/accounts.ts
delete mode 100644 server/tests/api/check-params/blocklist.ts
delete mode 100644 server/tests/api/check-params/bulk.ts
delete mode 100644 server/tests/api/check-params/channel-import-videos.ts
delete mode 100644 server/tests/api/check-params/config.ts
delete mode 100644 server/tests/api/check-params/contact-form.ts
delete mode 100644 server/tests/api/check-params/custom-pages.ts
delete mode 100644 server/tests/api/check-params/debug.ts
delete mode 100644 server/tests/api/check-params/follows.ts
delete mode 100644 server/tests/api/check-params/index.ts
delete mode 100644 server/tests/api/check-params/jobs.ts
delete mode 100644 server/tests/api/check-params/live.ts
delete mode 100644 server/tests/api/check-params/logs.ts
delete mode 100644 server/tests/api/check-params/metrics.ts
delete mode 100644 server/tests/api/check-params/my-user.ts
delete mode 100644 server/tests/api/check-params/plugins.ts
delete mode 100644 server/tests/api/check-params/redundancy.ts
delete mode 100644 server/tests/api/check-params/registrations.ts
delete mode 100644 server/tests/api/check-params/runners.ts
delete mode 100644 server/tests/api/check-params/search.ts
delete mode 100644 server/tests/api/check-params/services.ts
delete mode 100644 server/tests/api/check-params/transcoding.ts
delete mode 100644 server/tests/api/check-params/two-factor.ts
delete mode 100644 server/tests/api/check-params/upload-quota.ts
delete mode 100644 server/tests/api/check-params/user-notifications.ts
delete mode 100644 server/tests/api/check-params/user-subscriptions.ts
delete mode 100644 server/tests/api/check-params/users-admin.ts
delete mode 100644 server/tests/api/check-params/users-emails.ts
delete mode 100644 server/tests/api/check-params/video-blacklist.ts
delete mode 100644 server/tests/api/check-params/video-captions.ts
delete mode 100644 server/tests/api/check-params/video-channel-syncs.ts
delete mode 100644 server/tests/api/check-params/video-channels.ts
delete mode 100644 server/tests/api/check-params/video-comments.ts
delete mode 100644 server/tests/api/check-params/video-files.ts
delete mode 100644 server/tests/api/check-params/video-imports.ts
delete mode 100644 server/tests/api/check-params/video-passwords.ts
delete mode 100644 server/tests/api/check-params/video-playlists.ts
delete mode 100644 server/tests/api/check-params/video-source.ts
delete mode 100644 server/tests/api/check-params/video-storyboards.ts
delete mode 100644 server/tests/api/check-params/video-studio.ts
delete mode 100644 server/tests/api/check-params/video-token.ts
delete mode 100644 server/tests/api/check-params/videos-common-filters.ts
delete mode 100644 server/tests/api/check-params/videos-history.ts
delete mode 100644 server/tests/api/check-params/videos-overviews.ts
delete mode 100644 server/tests/api/check-params/videos.ts
delete mode 100644 server/tests/api/check-params/views.ts
delete mode 100644 server/tests/api/index.ts
delete mode 100644 server/tests/api/live/index.ts
delete mode 100644 server/tests/api/live/live-constraints.ts
delete mode 100644 server/tests/api/live/live-fast-restream.ts
delete mode 100644 server/tests/api/live/live-permanent.ts
delete mode 100644 server/tests/api/live/live-rtmps.ts
delete mode 100644 server/tests/api/live/live-save-replay.ts
delete mode 100644 server/tests/api/live/live-socket-messages.ts
delete mode 100644 server/tests/api/live/live.ts
delete mode 100644 server/tests/api/moderation/abuses.ts
delete mode 100644 server/tests/api/moderation/blocklist-notification.ts
delete mode 100644 server/tests/api/moderation/blocklist.ts
delete mode 100644 server/tests/api/moderation/index.ts
delete mode 100644 server/tests/api/moderation/video-blacklist.ts
delete mode 100644 server/tests/api/notifications/admin-notifications.ts
delete mode 100644 server/tests/api/notifications/comments-notifications.ts
delete mode 100644 server/tests/api/notifications/index.ts
delete mode 100644 server/tests/api/notifications/moderation-notifications.ts
delete mode 100644 server/tests/api/notifications/notifications-api.ts
delete mode 100644 server/tests/api/notifications/registrations-notifications.ts
delete mode 100644 server/tests/api/notifications/user-notifications.ts
delete mode 100644 server/tests/api/object-storage/index.ts
delete mode 100644 server/tests/api/object-storage/live.ts
delete mode 100644 server/tests/api/object-storage/video-imports.ts
delete mode 100644 server/tests/api/object-storage/video-static-file-privacy.ts
delete mode 100644 server/tests/api/object-storage/videos.ts
delete mode 100644 server/tests/api/redundancy/index.ts
delete mode 100644 server/tests/api/redundancy/manage-redundancy.ts
delete mode 100644 server/tests/api/redundancy/redundancy-constraints.ts
delete mode 100644 server/tests/api/redundancy/redundancy.ts
delete mode 100644 server/tests/api/runners/index.ts
delete mode 100644 server/tests/api/runners/runner-common.ts
delete mode 100644 server/tests/api/runners/runner-live-transcoding.ts
delete mode 100644 server/tests/api/runners/runner-socket.ts
delete mode 100644 server/tests/api/runners/runner-studio-transcoding.ts
delete mode 100644 server/tests/api/runners/runner-vod-transcoding.ts
delete mode 100644 server/tests/api/search/index.ts
delete mode 100644 server/tests/api/search/search-activitypub-video-channels.ts
delete mode 100644 server/tests/api/search/search-activitypub-video-playlists.ts
delete mode 100644 server/tests/api/search/search-activitypub-videos.ts
delete mode 100644 server/tests/api/search/search-channels.ts
delete mode 100644 server/tests/api/search/search-index.ts
delete mode 100644 server/tests/api/search/search-playlists.ts
delete mode 100644 server/tests/api/search/search-videos.ts
delete mode 100644 server/tests/api/server/auto-follows.ts
delete mode 100644 server/tests/api/server/bulk.ts
delete mode 100644 server/tests/api/server/config-defaults.ts
delete mode 100644 server/tests/api/server/config.ts
delete mode 100644 server/tests/api/server/contact-form.ts
delete mode 100644 server/tests/api/server/email.ts
delete mode 100644 server/tests/api/server/follow-constraints.ts
delete mode 100644 server/tests/api/server/follows-moderation.ts
delete mode 100644 server/tests/api/server/follows.ts
delete mode 100644 server/tests/api/server/handle-down.ts
delete mode 100644 server/tests/api/server/homepage.ts
delete mode 100644 server/tests/api/server/index.ts
delete mode 100644 server/tests/api/server/jobs.ts
delete mode 100644 server/tests/api/server/logs.ts
delete mode 100644 server/tests/api/server/no-client.ts
delete mode 100644 server/tests/api/server/open-telemetry.ts
delete mode 100644 server/tests/api/server/plugins.ts
delete mode 100644 server/tests/api/server/proxy.ts
delete mode 100644 server/tests/api/server/reverse-proxy.ts
delete mode 100644 server/tests/api/server/services.ts
delete mode 100644 server/tests/api/server/slow-follows.ts
delete mode 100644 server/tests/api/server/stats.ts
delete mode 100644 server/tests/api/server/tracker.ts
delete mode 100644 server/tests/api/transcoding/audio-only.ts
delete mode 100644 server/tests/api/transcoding/create-transcoding.ts
delete mode 100644 server/tests/api/transcoding/hls.ts
delete mode 100644 server/tests/api/transcoding/index.ts
delete mode 100644 server/tests/api/transcoding/transcoder.ts
delete mode 100644 server/tests/api/transcoding/update-while-transcoding.ts
delete mode 100644 server/tests/api/transcoding/video-studio.ts
delete mode 100644 server/tests/api/users/index.ts
delete mode 100644 server/tests/api/users/oauth.ts
delete mode 100644 server/tests/api/users/registrations.ts
delete mode 100644 server/tests/api/users/two-factor.ts
delete mode 100644 server/tests/api/users/user-subscriptions.ts
delete mode 100644 server/tests/api/users/user-videos.ts
delete mode 100644 server/tests/api/users/users-email-verification.ts
delete mode 100644 server/tests/api/users/users-multiple-servers.ts
delete mode 100644 server/tests/api/users/users.ts
delete mode 100644 server/tests/api/videos/channel-import-videos.ts
delete mode 100644 server/tests/api/videos/index.ts
delete mode 100644 server/tests/api/videos/multiple-servers.ts
delete mode 100644 server/tests/api/videos/resumable-upload.ts
delete mode 100644 server/tests/api/videos/single-server.ts
delete mode 100644 server/tests/api/videos/video-captions.ts
delete mode 100644 server/tests/api/videos/video-change-ownership.ts
delete mode 100644 server/tests/api/videos/video-channel-syncs.ts
delete mode 100644 server/tests/api/videos/video-channels.ts
delete mode 100644 server/tests/api/videos/video-comments.ts
delete mode 100644 server/tests/api/videos/video-description.ts
delete mode 100644 server/tests/api/videos/video-files.ts
delete mode 100644 server/tests/api/videos/video-imports.ts
delete mode 100644 server/tests/api/videos/video-nsfw.ts
delete mode 100644 server/tests/api/videos/video-passwords.ts
delete mode 100644 server/tests/api/videos/video-playlist-thumbnails.ts
delete mode 100644 server/tests/api/videos/video-playlists.ts
delete mode 100644 server/tests/api/videos/video-privacy.ts
delete mode 100644 server/tests/api/videos/video-schedule-update.ts
delete mode 100644 server/tests/api/videos/video-source.ts
delete mode 100644 server/tests/api/videos/video-static-file-privacy.ts
delete mode 100644 server/tests/api/videos/video-storyboard.ts
delete mode 100644 server/tests/api/videos/videos-common-filters.ts
delete mode 100644 server/tests/api/videos/videos-history.ts
delete mode 100644 server/tests/api/videos/videos-overview.ts
delete mode 100644 server/tests/api/views/index.ts
delete mode 100644 server/tests/api/views/video-views-counter.ts
delete mode 100644 server/tests/api/views/video-views-overall-stats.ts
delete mode 100644 server/tests/api/views/video-views-retention-stats.ts
delete mode 100644 server/tests/api/views/video-views-timeserie-stats.ts
delete mode 100644 server/tests/api/views/videos-views-cleaner.ts
delete mode 100644 server/tests/cli/create-generate-storyboard-job.ts
delete mode 100644 server/tests/cli/create-import-video-file-job.ts
delete mode 100644 server/tests/cli/create-move-video-storage-job.ts
delete mode 100644 server/tests/cli/index.ts
delete mode 100644 server/tests/cli/peertube.ts
delete mode 100644 server/tests/cli/plugins.ts
delete mode 100644 server/tests/cli/prune-storage.ts
delete mode 100644 server/tests/cli/regenerate-thumbnails.ts
delete mode 100644 server/tests/cli/reset-password.ts
delete mode 100644 server/tests/cli/update-host.ts
delete mode 100644 server/tests/client.ts
delete mode 100644 server/tests/external-plugins/akismet.ts
delete mode 100644 server/tests/external-plugins/auth-ldap.ts
delete mode 100644 server/tests/external-plugins/auto-block-videos.ts
delete mode 100644 server/tests/external-plugins/auto-mute.ts
delete mode 100644 server/tests/external-plugins/index.ts
delete mode 100644 server/tests/feeds/feeds.ts
delete mode 100644 server/tests/feeds/index.ts
delete mode 100644 server/tests/fixtures/60fps_720p_small.mp4
delete mode 100644 server/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/bad-http-signature.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/bad-public-key.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/create-bad-signature.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/create.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/http-signature.json
delete mode 100644 server/tests/fixtures/ap-json/mastodon/public-key.json
delete mode 100644 server/tests/fixtures/ap-json/peertube/announce-without-context.json
delete mode 100644 server/tests/fixtures/ap-json/peertube/invalid-keys.json
delete mode 100644 server/tests/fixtures/ap-json/peertube/keys.json
delete mode 100644 server/tests/fixtures/avatar-big.png
delete mode 100644 server/tests/fixtures/avatar-resized-120x120.gif
delete mode 100644 server/tests/fixtures/avatar-resized-120x120.png
delete mode 100644 server/tests/fixtures/avatar-resized-48x48.gif
delete mode 100644 server/tests/fixtures/avatar-resized-48x48.png
delete mode 100644 server/tests/fixtures/avatar.gif
delete mode 100644 server/tests/fixtures/avatar.png
delete mode 100644 server/tests/fixtures/avatar2-resized-120x120.png
delete mode 100644 server/tests/fixtures/avatar2-resized-48x48.png
delete mode 100644 server/tests/fixtures/avatar2.png
delete mode 100644 server/tests/fixtures/banner-resized.jpg
delete mode 100644 server/tests/fixtures/banner.jpg
delete mode 100644 server/tests/fixtures/custom-preview-big.png
delete mode 100644 server/tests/fixtures/custom-preview.jpg
delete mode 100644 server/tests/fixtures/custom-thumbnail-big.jpg
delete mode 100644 server/tests/fixtures/custom-thumbnail.jpg
delete mode 100644 server/tests/fixtures/custom-thumbnail.png
delete mode 100644 server/tests/fixtures/exif.jpg
delete mode 100644 server/tests/fixtures/exif.png
delete mode 100644 server/tests/fixtures/live/0-000067.ts
delete mode 100644 server/tests/fixtures/live/0-000068.ts
delete mode 100644 server/tests/fixtures/live/0-000069.ts
delete mode 100644 server/tests/fixtures/live/0-000070.ts
delete mode 100644 server/tests/fixtures/live/0.m3u8
delete mode 100644 server/tests/fixtures/live/1-000067.ts
delete mode 100644 server/tests/fixtures/live/1-000068.ts
delete mode 100644 server/tests/fixtures/live/1-000069.ts
delete mode 100644 server/tests/fixtures/live/1-000070.ts
delete mode 100644 server/tests/fixtures/live/1.m3u8
delete mode 100644 server/tests/fixtures/live/master.m3u8
delete mode 100644 server/tests/fixtures/low-bitrate.mp4
delete mode 100644 server/tests/fixtures/peertube-plugin-test-broken/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-broken/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-three/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-three/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-filter-translations/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-filter-translations/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-five/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-five/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-four/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-four/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-native/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-native/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-six/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-six/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-transcoding-one/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-transcoding-two/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-transcoding-two/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-unloading/lib.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-unloading/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-unloading/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-video-constants/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-video-constants/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test-websocket/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test-websocket/package.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test/languages/fr.json
delete mode 100644 server/tests/fixtures/peertube-plugin-test/main.js
delete mode 100644 server/tests/fixtures/peertube-plugin-test/package.json
delete mode 100644 server/tests/fixtures/rtmps.cert
delete mode 100644 server/tests/fixtures/rtmps.key
delete mode 100644 server/tests/fixtures/sample.ogg
delete mode 100644 server/tests/fixtures/subtitle-bad.txt
delete mode 100644 server/tests/fixtures/subtitle-good.srt
delete mode 100644 server/tests/fixtures/subtitle-good1.vtt
delete mode 100644 server/tests/fixtures/subtitle-good2.vtt
delete mode 100644 server/tests/fixtures/thumbnail-playlist.jpg
delete mode 100644 server/tests/fixtures/video-720p.torrent
delete mode 100644 server/tests/fixtures/video_import_preview.jpg
delete mode 100644 server/tests/fixtures/video_import_preview_yt_dlp.jpg
delete mode 100644 server/tests/fixtures/video_import_thumbnail.jpg
delete mode 100644 server/tests/fixtures/video_import_thumbnail_yt_dlp.jpg
delete mode 100644 server/tests/fixtures/video_short.avi
delete mode 100644 server/tests/fixtures/video_short.mkv
delete mode 100644 server/tests/fixtures/video_short.mp4
delete mode 100644 server/tests/fixtures/video_short.mp4.jpg
delete mode 100644 server/tests/fixtures/video_short.ogv
delete mode 100644 server/tests/fixtures/video_short.ogv.jpg
delete mode 100644 server/tests/fixtures/video_short.webm
delete mode 100644 server/tests/fixtures/video_short.webm.jpg
delete mode 100644 server/tests/fixtures/video_short1-preview.webm.jpg
delete mode 100644 server/tests/fixtures/video_short1.webm
delete mode 100644 server/tests/fixtures/video_short1.webm.jpg
delete mode 100644 server/tests/fixtures/video_short2.webm
delete mode 100644 server/tests/fixtures/video_short2.webm.jpg
delete mode 100644 server/tests/fixtures/video_short3.webm
delete mode 100644 server/tests/fixtures/video_short3.webm.jpg
delete mode 100644 server/tests/fixtures/video_short_0p.mp4
delete mode 100644 server/tests/fixtures/video_short_144p.m3u8
delete mode 100644 server/tests/fixtures/video_short_144p.mp4
delete mode 100644 server/tests/fixtures/video_short_240p.m3u8
delete mode 100644 server/tests/fixtures/video_short_240p.mp4
delete mode 100644 server/tests/fixtures/video_short_360p.m3u8
delete mode 100644 server/tests/fixtures/video_short_360p.mp4
delete mode 100644 server/tests/fixtures/video_short_480.webm
delete mode 100644 server/tests/fixtures/video_short_480p.m3u8
delete mode 100644 server/tests/fixtures/video_short_480p.mp4
delete mode 100644 server/tests/fixtures/video_short_4k.mp4
delete mode 100644 server/tests/fixtures/video_short_720p.m3u8
delete mode 100644 server/tests/fixtures/video_short_720p.mp4
delete mode 100644 server/tests/fixtures/video_short_fake.webm
delete mode 100644 server/tests/fixtures/video_short_mp3_256k.mp4
delete mode 100644 server/tests/fixtures/video_short_no_audio.mp4
delete mode 100644 server/tests/fixtures/video_very_long_10p.mp4
delete mode 100644 server/tests/fixtures/video_very_short_240p.mp4
delete mode 100644 server/tests/helpers/comment-model.ts
delete mode 100644 server/tests/helpers/core-utils.ts
delete mode 100644 server/tests/helpers/crypto.ts
delete mode 100644 server/tests/helpers/dns.ts
delete mode 100644 server/tests/helpers/image.ts
delete mode 100644 server/tests/helpers/index.ts
delete mode 100644 server/tests/helpers/markdown.ts
delete mode 100644 server/tests/helpers/request.ts
delete mode 100644 server/tests/helpers/validator.ts
delete mode 100644 server/tests/helpers/version.ts
delete mode 100644 server/tests/index.ts
delete mode 100644 server/tests/lib/index.ts
delete mode 100644 server/tests/lib/video-constant-registry-factory.ts
delete mode 100644 server/tests/misc-endpoints.ts
delete mode 100644 server/tests/peertube-runner/client-cli.ts
delete mode 100644 server/tests/peertube-runner/index.ts
delete mode 100644 server/tests/peertube-runner/live-transcoding.ts
delete mode 100644 server/tests/peertube-runner/studio-transcoding.ts
delete mode 100644 server/tests/peertube-runner/vod-transcoding.ts
delete mode 100644 server/tests/plugins/action-hooks.ts
delete mode 100644 server/tests/plugins/external-auth.ts
delete mode 100644 server/tests/plugins/filter-hooks.ts
delete mode 100644 server/tests/plugins/html-injection.ts
delete mode 100644 server/tests/plugins/id-and-pass-auth.ts
delete mode 100644 server/tests/plugins/index.ts
delete mode 100644 server/tests/plugins/plugin-helpers.ts
delete mode 100644 server/tests/plugins/plugin-router.ts
delete mode 100644 server/tests/plugins/plugin-storage.ts
delete mode 100644 server/tests/plugins/plugin-transcoding.ts
delete mode 100644 server/tests/plugins/plugin-unloading.ts
delete mode 100644 server/tests/plugins/plugin-websocket.ts
delete mode 100644 server/tests/plugins/translations.ts
delete mode 100644 server/tests/plugins/video-constants.ts
delete mode 100644 server/tests/shared/actors.ts
delete mode 100644 server/tests/shared/captions.ts
delete mode 100644 server/tests/shared/checks.ts
delete mode 100644 server/tests/shared/directories.ts
delete mode 100644 server/tests/shared/generate.ts
delete mode 100644 server/tests/shared/index.ts
delete mode 100644 server/tests/shared/live.ts
delete mode 100644 server/tests/shared/mock-servers/index.ts
delete mode 100644 server/tests/shared/mock-servers/mock-429.ts
delete mode 100644 server/tests/shared/mock-servers/mock-email.ts
delete mode 100644 server/tests/shared/mock-servers/mock-http.ts
delete mode 100644 server/tests/shared/mock-servers/mock-instances-index.ts
delete mode 100644 server/tests/shared/mock-servers/mock-joinpeertube-versions.ts
delete mode 100644 server/tests/shared/mock-servers/mock-object-storage.ts
delete mode 100644 server/tests/shared/mock-servers/mock-plugin-blocklist.ts
delete mode 100644 server/tests/shared/mock-servers/mock-proxy.ts
delete mode 100644 server/tests/shared/mock-servers/shared.ts
delete mode 100644 server/tests/shared/notifications.ts
delete mode 100644 server/tests/shared/peertube-runner-process.ts
delete mode 100644 server/tests/shared/plugins.ts
delete mode 100644 server/tests/shared/requests.ts
delete mode 100644 server/tests/shared/sql-command.ts
delete mode 100644 server/tests/shared/streaming-playlists.ts
delete mode 100644 server/tests/shared/tests.ts
delete mode 100644 server/tests/shared/tracker.ts
delete mode 100644 server/tests/shared/video-playlists.ts
delete mode 100644 server/tests/shared/videos.ts
delete mode 100644 server/tests/shared/views.ts
delete mode 100644 server/tests/shared/webtorrent.ts
(limited to 'server/tests')
diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts
deleted file mode 100644
index d67175e20..000000000
--- a/server/tests/api/activitypub/cleaner.ts
+++ /dev/null
@@ -1,342 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { SQLCommand } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test AP cleaner', function () {
- let servers: PeerTubeServer[] = []
- const sqlCommands: SQLCommand[] = []
-
- let videoUUID1: string
- let videoUUID2: string
- let videoUUID3: string
-
- let videoUUIDs: string[]
-
- before(async function () {
- this.timeout(120000)
-
- const config = {
- federation: {
- videos: { cleanup_remote_interactions: true }
- }
- }
- servers = await createMultipleServers(3, config)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- await Promise.all([
- doubleFollow(servers[0], servers[1]),
- doubleFollow(servers[1], servers[2]),
- doubleFollow(servers[0], servers[2])
- ])
-
- // Update 1 local share, check 6 shares
-
- // Create 1 comment per video
- // Update 1 remote URL and 1 local URL on
-
- videoUUID1 = (await servers[0].videos.quickUpload({ name: 'server 1' })).uuid
- videoUUID2 = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
- videoUUID3 = (await servers[2].videos.quickUpload({ name: 'server 3' })).uuid
-
- videoUUIDs = [ videoUUID1, videoUUID2, videoUUID3 ]
-
- await waitJobs(servers)
-
- for (const server of servers) {
- for (const uuid of videoUUIDs) {
- await server.videos.rate({ id: uuid, rating: 'like' })
- await server.comments.createThread({ videoId: uuid, text: 'comment' })
- }
-
- sqlCommands.push(new SQLCommand(server))
- }
-
- await waitJobs(servers)
- })
-
- it('Should have the correct likes', async function () {
- for (const server of servers) {
- for (const uuid of videoUUIDs) {
- const video = await server.videos.get({ id: uuid })
-
- expect(video.likes).to.equal(3)
- expect(video.dislikes).to.equal(0)
- }
- }
- })
-
- it('Should destroy server 3 internal likes and correctly clean them', async function () {
- this.timeout(20000)
-
- await sqlCommands[2].deleteAll('accountVideoRate')
- for (const uuid of videoUUIDs) {
- await sqlCommands[2].setVideoField(uuid, 'likes', '0')
- }
-
- await wait(5000)
- await waitJobs(servers)
-
- // Updated rates of my video
- {
- const video = await servers[0].videos.get({ id: videoUUID1 })
- expect(video.likes).to.equal(2)
- expect(video.dislikes).to.equal(0)
- }
-
- // Did not update rates of a remote video
- {
- const video = await servers[0].videos.get({ id: videoUUID2 })
- expect(video.likes).to.equal(3)
- expect(video.dislikes).to.equal(0)
- }
- })
-
- it('Should update rates to dislikes', async function () {
- this.timeout(20000)
-
- for (const server of servers) {
- for (const uuid of videoUUIDs) {
- await server.videos.rate({ id: uuid, rating: 'dislike' })
- }
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- for (const uuid of videoUUIDs) {
- const video = await server.videos.get({ id: uuid })
- expect(video.likes).to.equal(0)
- expect(video.dislikes).to.equal(3)
- }
- }
- })
-
- it('Should destroy server 3 internal dislikes and correctly clean them', async function () {
- this.timeout(20000)
-
- await sqlCommands[2].deleteAll('accountVideoRate')
-
- for (const uuid of videoUUIDs) {
- await sqlCommands[2].setVideoField(uuid, 'dislikes', '0')
- }
-
- await wait(5000)
- await waitJobs(servers)
-
- // Updated rates of my video
- {
- const video = await servers[0].videos.get({ id: videoUUID1 })
- expect(video.likes).to.equal(0)
- expect(video.dislikes).to.equal(2)
- }
-
- // Did not update rates of a remote video
- {
- const video = await servers[0].videos.get({ id: videoUUID2 })
- expect(video.likes).to.equal(0)
- expect(video.dislikes).to.equal(3)
- }
- })
-
- it('Should destroy server 3 internal shares and correctly clean them', async function () {
- this.timeout(20000)
-
- const preCount = await sqlCommands[0].getVideoShareCount()
- expect(preCount).to.equal(6)
-
- await sqlCommands[2].deleteAll('videoShare')
- await wait(5000)
- await waitJobs(servers)
-
- // Still 6 because we don't have remote shares on local videos
- const postCount = await sqlCommands[0].getVideoShareCount()
- expect(postCount).to.equal(6)
- })
-
- it('Should destroy server 3 internal comments and correctly clean them', async function () {
- this.timeout(20000)
-
- {
- const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
- expect(total).to.equal(3)
- }
-
- await sqlCommands[2].deleteAll('videoComment')
-
- await wait(5000)
- await waitJobs(servers)
-
- {
- const { total } = await servers[0].comments.listThreads({ videoId: videoUUID1 })
- expect(total).to.equal(2)
- }
- })
-
- it('Should correctly update rate URLs', async function () {
- this.timeout(30000)
-
- async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
- const query = `SELECT "videoId", "accountVideoRate".url FROM "accountVideoRate" ` +
- `INNER JOIN video ON "accountVideoRate"."videoId" = video.id AND remote IS ${remote} WHERE "accountVideoRate"."url" LIKE '${like}'`
- const res = await sqlCommands[0].selectQuery<{ url: string }>(query)
-
- for (const rate of res) {
- const matcher = new RegExp(`^${ofServerUrl}/accounts/root/dislikes/\\d+${urlSuffix}$`)
- expect(rate.url).to.match(matcher)
- }
- }
-
- async function checkLocal () {
- const startsWith = 'http://' + servers[0].host + '%'
- // On local videos
- await check(startsWith, servers[0].url, '', 'false')
- // On remote videos
- await check(startsWith, servers[0].url, '', 'true')
- }
-
- async function checkRemote (suffix: string) {
- const startsWith = 'http://' + servers[1].host + '%'
- // On local videos
- await check(startsWith, servers[1].url, suffix, 'false')
- // On remote videos, we should not update URLs so no suffix
- await check(startsWith, servers[1].url, '', 'true')
- }
-
- await checkLocal()
- await checkRemote('')
-
- {
- const query = `UPDATE "accountVideoRate" SET url = url || 'stan'`
- await sqlCommands[1].updateQuery(query)
-
- await wait(5000)
- await waitJobs(servers)
- }
-
- await checkLocal()
- await checkRemote('stan')
- })
-
- it('Should correctly update comment URLs', async function () {
- this.timeout(30000)
-
- async function check (like: string, ofServerUrl: string, urlSuffix: string, remote: 'true' | 'false') {
- const query = `SELECT "videoId", "videoComment".url, uuid as "videoUUID" FROM "videoComment" ` +
- `INNER JOIN video ON "videoComment"."videoId" = video.id AND remote IS ${remote} WHERE "videoComment"."url" LIKE '${like}'`
-
- const res = await sqlCommands[0].selectQuery<{ url: string, videoUUID: string }>(query)
-
- for (const comment of res) {
- const matcher = new RegExp(`${ofServerUrl}/videos/watch/${comment.videoUUID}/comments/\\d+${urlSuffix}`)
- expect(comment.url).to.match(matcher)
- }
- }
-
- async function checkLocal () {
- const startsWith = 'http://' + servers[0].host + '%'
- // On local videos
- await check(startsWith, servers[0].url, '', 'false')
- // On remote videos
- await check(startsWith, servers[0].url, '', 'true')
- }
-
- async function checkRemote (suffix: string) {
- const startsWith = 'http://' + servers[1].host + '%'
- // On local videos
- await check(startsWith, servers[1].url, suffix, 'false')
- // On remote videos, we should not update URLs so no suffix
- await check(startsWith, servers[1].url, '', 'true')
- }
-
- {
- const query = `UPDATE "videoComment" SET url = url || 'kyle'`
- await sqlCommands[1].updateQuery(query)
-
- await wait(5000)
- await waitJobs(servers)
- }
-
- await checkLocal()
- await checkRemote('kyle')
- })
-
- it('Should remove unavailable remote resources', async function () {
- this.timeout(240000)
-
- async function expectNotDeleted () {
- {
- const video = await servers[0].videos.get({ id: uuid })
-
- expect(video.likes).to.equal(3)
- expect(video.dislikes).to.equal(0)
- }
-
- {
- const { total } = await servers[0].comments.listThreads({ videoId: uuid })
- expect(total).to.equal(3)
- }
- }
-
- async function expectDeleted () {
- {
- const video = await servers[0].videos.get({ id: uuid })
-
- expect(video.likes).to.equal(2)
- expect(video.dislikes).to.equal(0)
- }
-
- {
- const { total } = await servers[0].comments.listThreads({ videoId: uuid })
- expect(total).to.equal(2)
- }
- }
-
- const uuid = (await servers[0].videos.quickUpload({ name: 'server 1 video 2' })).uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.videos.rate({ id: uuid, rating: 'like' })
- await server.comments.createThread({ videoId: uuid, text: 'comment' })
- }
-
- await waitJobs(servers)
-
- await expectNotDeleted()
-
- await servers[1].kill()
-
- await wait(5000)
- await expectNotDeleted()
-
- let continueWhile = true
-
- do {
- try {
- await expectDeleted()
- continueWhile = false
- } catch {
- }
- } while (continueWhile)
- })
-
- after(async function () {
- for (const sql of sqlCommands) {
- await sql.cleanup()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/activitypub/client.ts b/server/tests/api/activitypub/client.ts
deleted file mode 100644
index 572a358a0..000000000
--- a/server/tests/api/activitypub/client.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { processViewersStats } from '@server/tests/shared'
-import { HttpStatusCode, VideoPlaylistPrivacy, WatchActionObject } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeActivityPubGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test activitypub', function () {
- let servers: PeerTubeServer[] = []
- let video: { id: number, uuid: string, shortUUID: string }
- let playlist: { id: number, uuid: string, shortUUID: string }
-
- async function testAccount (path: string) {
- const res = await makeActivityPubGetRequest(servers[0].url, path)
- const object = res.body
-
- expect(object.type).to.equal('Person')
- expect(object.id).to.equal(servers[0].url + '/accounts/root')
- expect(object.name).to.equal('root')
- expect(object.preferredUsername).to.equal('root')
- }
-
- async function testChannel (path: string) {
- const res = await makeActivityPubGetRequest(servers[0].url, path)
- const object = res.body
-
- expect(object.type).to.equal('Group')
- expect(object.id).to.equal(servers[0].url + '/video-channels/root_channel')
- expect(object.name).to.equal('Main root channel')
- expect(object.preferredUsername).to.equal('root_channel')
- }
-
- async function testVideo (path: string) {
- const res = await makeActivityPubGetRequest(servers[0].url, path)
- const object = res.body
-
- expect(object.type).to.equal('Video')
- expect(object.id).to.equal(servers[0].url + '/videos/watch/' + video.uuid)
- expect(object.name).to.equal('video')
- }
-
- async function testPlaylist (path: string) {
- const res = await makeActivityPubGetRequest(servers[0].url, path)
- const object = res.body
-
- expect(object.type).to.equal('Playlist')
- expect(object.id).to.equal(servers[0].url + '/video-playlists/' + playlist.uuid)
- expect(object.name).to.equal('playlist')
- }
-
- before(async function () {
- this.timeout(30000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- {
- video = await servers[0].videos.quickUpload({ name: 'video' })
- }
-
- {
- const attributes = { displayName: 'playlist', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[0].store.channel.id }
- playlist = await servers[0].playlists.create({ attributes })
- }
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should return the account object', async function () {
- await testAccount('/accounts/root')
- await testAccount('/a/root')
- })
-
- it('Should return the channel object', async function () {
- await testChannel('/video-channels/root_channel')
- await testChannel('/c/root_channel')
- })
-
- it('Should return the video object', async function () {
- await testVideo('/videos/watch/' + video.id)
- await testVideo('/videos/watch/' + video.uuid)
- await testVideo('/videos/watch/' + video.shortUUID)
- await testVideo('/w/' + video.id)
- await testVideo('/w/' + video.uuid)
- await testVideo('/w/' + video.shortUUID)
- })
-
- it('Should return the playlist object', async function () {
- await testPlaylist('/video-playlists/' + playlist.id)
- await testPlaylist('/video-playlists/' + playlist.uuid)
- await testPlaylist('/video-playlists/' + playlist.shortUUID)
- await testPlaylist('/w/p/' + playlist.id)
- await testPlaylist('/w/p/' + playlist.uuid)
- await testPlaylist('/w/p/' + playlist.shortUUID)
- await testPlaylist('/videos/watch/playlist/' + playlist.id)
- await testPlaylist('/videos/watch/playlist/' + playlist.uuid)
- await testPlaylist('/videos/watch/playlist/' + playlist.shortUUID)
- })
-
- it('Should redirect to the origin video object', async function () {
- const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + video.uuid, HttpStatusCode.FOUND_302)
-
- expect(res.header.location).to.equal(servers[0].url + '/videos/watch/' + video.uuid)
- })
-
- it('Should return the watch action', async function () {
- this.timeout(50000)
-
- await servers[0].views.simulateViewer({ id: video.uuid, currentTimes: [ 0, 2 ] })
- await processViewersStats(servers)
-
- const res = await makeActivityPubGetRequest(servers[0].url, '/videos/local-viewer/1', HttpStatusCode.OK_200)
-
- const object: WatchActionObject = res.body
- expect(object.type).to.equal('WatchAction')
- expect(object.duration).to.equal('PT2S')
- expect(object.actionStatus).to.equal('CompletedActionStatus')
- expect(object.watchSections).to.have.lengthOf(1)
- expect(object.watchSections[0].startTimestamp).to.equal(0)
- expect(object.watchSections[0].endTimestamp).to.equal(2)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/activitypub/fetch.ts b/server/tests/api/activitypub/fetch.ts
deleted file mode 100644
index 3899a6a49..000000000
--- a/server/tests/api/activitypub/fetch.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { SQLCommand } from '@server/tests/shared'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test ActivityPub fetcher', function () {
- let servers: PeerTubeServer[]
- let sqlCommandServer1: SQLCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- const user = { username: 'user1', password: 'password' }
- for (const server of servers) {
- await server.users.create({ username: user.username, password: user.password })
- }
-
- const userAccessToken = await servers[0].login.getAccessToken(user)
-
- await servers[0].videos.upload({ attributes: { name: 'video root' } })
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'bad video root' } })
- await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'video user' } })
-
- sqlCommandServer1 = new SQLCommand(servers[0])
-
- {
- const to = servers[0].url + '/accounts/user1'
- const value = servers[1].url + '/accounts/user1'
- await sqlCommandServer1.setActorField(to, 'url', value)
- }
-
- {
- const value = servers[2].url + '/videos/watch/' + uuid
- await sqlCommandServer1.setVideoField(uuid, 'url', value)
- }
- })
-
- it('Should add only the video with a valid actor URL', async function () {
- this.timeout(60000)
-
- await doubleFollow(servers[0], servers[1])
- await waitJobs(servers)
-
- {
- const { total, data } = await servers[0].videos.list({ sort: 'createdAt' })
-
- expect(total).to.equal(3)
- expect(data[0].name).to.equal('video root')
- expect(data[1].name).to.equal('bad video root')
- expect(data[2].name).to.equal('video user')
- }
-
- {
- const { total, data } = await servers[1].videos.list({ sort: 'createdAt' })
-
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('video root')
- }
- })
-
- after(async function () {
- this.timeout(20000)
-
- await sqlCommandServer1.cleanup()
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/activitypub/helpers.ts b/server/tests/api/activitypub/helpers.ts
deleted file mode 100644
index bad86ef47..000000000
--- a/server/tests/api/activitypub/helpers.ts
+++ /dev/null
@@ -1,167 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { cloneDeep } from 'lodash'
-import { signAndContextify } from '@server/lib/activitypub/send'
-import { buildRequestStub } from '@server/tests/shared'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../../../helpers/peertube-crypto'
-
-describe('Test activity pub helpers', function () {
-
- describe('When checking the Linked Signature', function () {
-
- it('Should fail with an invalid Mastodon signature', async function () {
- const body = require(buildAbsoluteFixturePath('./ap-json/mastodon/create-bad-signature.json'))
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/public-key.json')).publicKey
- const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' }
-
- const result = await isJsonLDSignatureVerified(fromActor as any, body)
-
- expect(result).to.be.false
- })
-
- it('Should fail with an invalid public key', async function () {
- const body = require(buildAbsoluteFixturePath('./ap-json/mastodon/create.json'))
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/bad-public-key.json')).publicKey
- const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' }
-
- const result = await isJsonLDSignatureVerified(fromActor as any, body)
-
- expect(result).to.be.false
- })
-
- it('Should succeed with a valid Mastodon signature', async function () {
- const body = require(buildAbsoluteFixturePath('./ap-json/mastodon/create.json'))
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/public-key.json')).publicKey
- const fromActor = { publicKey, url: 'http://localhost:9002/accounts/peertube' }
-
- const result = await isJsonLDSignatureVerified(fromActor as any, body)
-
- expect(result).to.be.true
- })
-
- it('Should fail with an invalid PeerTube signature', async function () {
- const keys = require(buildAbsoluteFixturePath('./ap-json/peertube/invalid-keys.json'))
- const body = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
-
- const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
- const signedBody = await signAndContextify(actorSignature as any, body, 'Announce')
-
- const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' }
- const result = await isJsonLDSignatureVerified(fromActor as any, signedBody)
-
- expect(result).to.be.false
- })
-
- it('Should succeed with a valid PeerTube signature', async function () {
- const keys = require(buildAbsoluteFixturePath('./ap-json/peertube/keys.json'))
- const body = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
-
- const actorSignature = { url: 'http://localhost:9002/accounts/peertube', privateKey: keys.privateKey }
- const signedBody = await signAndContextify(actorSignature as any, body, 'Announce')
-
- const fromActor = { publicKey: keys.publicKey, url: 'http://localhost:9002/accounts/peertube' }
- const result = await isJsonLDSignatureVerified(fromActor as any, signedBody)
-
- expect(result).to.be.true
- })
- })
-
- describe('When checking HTTP signature', function () {
- it('Should fail with an invalid http signature', async function () {
- const req = buildRequestStub()
- req.method = 'POST'
- req.url = '/accounts/ronan/inbox'
-
- const mastodonObject = cloneDeep(require(buildAbsoluteFixturePath('./ap-json/mastodon/bad-http-signature.json')))
- req.body = mastodonObject.body
- req.headers = mastodonObject.headers
-
- const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/public-key.json')).publicKey
-
- const actor = { publicKey }
- const verified = isHTTPSignatureVerified(parsed, actor as any)
-
- expect(verified).to.be.false
- })
-
- it('Should fail with an invalid public key', async function () {
- const req = buildRequestStub()
- req.method = 'POST'
- req.url = '/accounts/ronan/inbox'
-
- const mastodonObject = cloneDeep(require(buildAbsoluteFixturePath('./ap-json/mastodon/http-signature.json')))
- req.body = mastodonObject.body
- req.headers = mastodonObject.headers
-
- const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/bad-public-key.json')).publicKey
-
- const actor = { publicKey }
- const verified = isHTTPSignatureVerified(parsed, actor as any)
-
- expect(verified).to.be.false
- })
-
- it('Should fail because of clock skew', async function () {
- const req = buildRequestStub()
- req.method = 'POST'
- req.url = '/accounts/ronan/inbox'
-
- const mastodonObject = cloneDeep(require(buildAbsoluteFixturePath('./ap-json/mastodon/http-signature.json')))
- req.body = mastodonObject.body
- req.headers = mastodonObject.headers
-
- let errored = false
- try {
- parseHTTPSignature(req)
- } catch {
- errored = true
- }
-
- expect(errored).to.be.true
- })
-
- it('Should with a scheme', async function () {
- const req = buildRequestStub()
- req.method = 'POST'
- req.url = '/accounts/ronan/inbox'
-
- const mastodonObject = cloneDeep(require(buildAbsoluteFixturePath('./ap-json/mastodon/http-signature.json')))
- req.body = mastodonObject.body
- req.headers = mastodonObject.headers
- req.headers = 'Signature ' + mastodonObject.headers
-
- let errored = false
- try {
- parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
- } catch {
- errored = true
- }
-
- expect(errored).to.be.true
- })
-
- it('Should succeed with a valid signature', async function () {
- const req = buildRequestStub()
- req.method = 'POST'
- req.url = '/accounts/ronan/inbox'
-
- const mastodonObject = cloneDeep(require(buildAbsoluteFixturePath('./ap-json/mastodon/http-signature.json')))
- req.body = mastodonObject.body
- req.headers = mastodonObject.headers
-
- const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
- const publicKey = require(buildAbsoluteFixturePath('./ap-json/mastodon/public-key.json')).publicKey
-
- const actor = { publicKey }
- const verified = isHTTPSignatureVerified(parsed, actor as any)
-
- expect(verified).to.be.true
- })
-
- })
-
-})
diff --git a/server/tests/api/activitypub/index.ts b/server/tests/api/activitypub/index.ts
deleted file mode 100644
index 324b444e4..000000000
--- a/server/tests/api/activitypub/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import './cleaner'
-import './client'
-import './fetch'
-import './refresher'
-import './helpers'
-import './security'
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts
deleted file mode 100644
index 4ea7929ec..000000000
--- a/server/tests/api/activitypub/refresher.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { SQLCommand } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test AP refresher', function () {
- let servers: PeerTubeServer[] = []
- let sqlCommandServer2: SQLCommand
- let videoUUID1: string
- let videoUUID2: string
- let videoUUID3: string
- let playlistUUID1: string
- let playlistUUID2: string
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- for (const server of servers) {
- await server.config.disableTranscoding()
- }
-
- {
- videoUUID1 = (await servers[1].videos.quickUpload({ name: 'video1' })).uuid
- videoUUID2 = (await servers[1].videos.quickUpload({ name: 'video2' })).uuid
- videoUUID3 = (await servers[1].videos.quickUpload({ name: 'video3' })).uuid
- }
-
- {
- const token1 = await servers[1].users.generateUserAndToken('user1')
- await servers[1].videos.upload({ token: token1, attributes: { name: 'video4' } })
-
- const token2 = await servers[1].users.generateUserAndToken('user2')
- await servers[1].videos.upload({ token: token2, attributes: { name: 'video5' } })
- }
-
- {
- const attributes = { displayName: 'playlist1', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].store.channel.id }
- const created = await servers[1].playlists.create({ attributes })
- playlistUUID1 = created.uuid
- }
-
- {
- const attributes = { displayName: 'playlist2', privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: servers[1].store.channel.id }
- const created = await servers[1].playlists.create({ attributes })
- playlistUUID2 = created.uuid
- }
-
- await doubleFollow(servers[0], servers[1])
-
- sqlCommandServer2 = new SQLCommand(servers[1])
- })
-
- describe('Videos refresher', function () {
-
- it('Should remove a deleted remote video', async function () {
- this.timeout(60000)
-
- await wait(10000)
-
- // Change UUID so the remote server returns a 404
- await sqlCommandServer2.setVideoField(videoUUID1, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174f')
-
- await servers[0].videos.get({ id: videoUUID1 })
- await servers[0].videos.get({ id: videoUUID2 })
-
- await waitJobs(servers)
-
- await servers[0].videos.get({ id: videoUUID1, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await servers[0].videos.get({ id: videoUUID2 })
- })
-
- it('Should not update a remote video if the remote instance is down', async function () {
- this.timeout(70000)
-
- await killallServers([ servers[1] ])
-
- await sqlCommandServer2.setVideoField(videoUUID3, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b174e')
-
- // Video will need a refresh
- await wait(10000)
-
- await servers[0].videos.get({ id: videoUUID3 })
- // The refresh should fail
- await waitJobs([ servers[0] ])
-
- await servers[1].run()
-
- await servers[0].videos.get({ id: videoUUID3 })
- })
- })
-
- describe('Actors refresher', function () {
-
- it('Should remove a deleted actor', async function () {
- this.timeout(60000)
-
- const command = servers[0].accounts
-
- await wait(10000)
-
- // Change actor name so the remote server returns a 404
- const to = servers[1].url + '/accounts/user2'
- await sqlCommandServer2.setActorField(to, 'preferredUsername', 'toto')
-
- await command.get({ accountName: 'user1@' + servers[1].host })
- await command.get({ accountName: 'user2@' + servers[1].host })
-
- await waitJobs(servers)
-
- await command.get({ accountName: 'user1@' + servers[1].host, expectedStatus: HttpStatusCode.OK_200 })
- await command.get({ accountName: 'user2@' + servers[1].host, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Playlist refresher', function () {
-
- it('Should remove a deleted playlist', async function () {
- this.timeout(60000)
-
- await wait(10000)
-
- // Change UUID so the remote server returns a 404
- await sqlCommandServer2.setPlaylistField(playlistUUID2, 'uuid', '304afe4f-39f9-4d49-8ed7-ac57b86b178e')
-
- await servers[0].playlists.get({ playlistId: playlistUUID1 })
- await servers[0].playlists.get({ playlistId: playlistUUID2 })
-
- await waitJobs(servers)
-
- await servers[0].playlists.get({ playlistId: playlistUUID1, expectedStatus: HttpStatusCode.OK_200 })
- await servers[0].playlists.get({ playlistId: playlistUUID2, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- after(async function () {
- await sqlCommandServer2.cleanup()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts
deleted file mode 100644
index 8e87361a9..000000000
--- a/server/tests/api/activitypub/security.ts
+++ /dev/null
@@ -1,321 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { buildDigest } from '@server/helpers/peertube-crypto'
-import { ACTIVITY_PUB, HTTP_SIGNATURE } from '@server/initializers/constants'
-import { activityPubContextify } from '@server/lib/activitypub/context'
-import { buildGlobalHeaders, signAndContextify } from '@server/lib/activitypub/send'
-import { makePOSTAPRequest, SQLCommand } from '@server/tests/shared'
-import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createMultipleServers, killallServers, PeerTubeServer } from '@shared/server-commands'
-
-function setKeysOfServer (onServer: SQLCommand, ofServerUrl: string, publicKey: string, privateKey: string) {
- const url = ofServerUrl + '/accounts/peertube'
-
- return Promise.all([
- onServer.setActorField(url, 'publicKey', publicKey),
- onServer.setActorField(url, 'privateKey', privateKey)
- ])
-}
-
-function setUpdatedAtOfServer (onServer: SQLCommand, ofServerUrl: string, updatedAt: string) {
- const url = ofServerUrl + '/accounts/peertube'
-
- return Promise.all([
- onServer.setActorField(url, 'createdAt', updatedAt),
- onServer.setActorField(url, 'updatedAt', updatedAt)
- ])
-}
-
-function getAnnounceWithoutContext (server: PeerTubeServer) {
- const json = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
- const result: typeof json = {}
-
- for (const key of Object.keys(json)) {
- if (Array.isArray(json[key])) {
- result[key] = json[key].map(v => v.replace(':9002', `:${server.port}`))
- } else {
- result[key] = json[key].replace(':9002', `:${server.port}`)
- }
- }
-
- return result
-}
-
-async function makeFollowRequest (to: { url: string }, by: { url: string, privateKey }) {
- const follow = {
- type: 'Follow',
- id: by.url + '/' + new Date().getTime(),
- actor: by.url,
- object: to.url
- }
-
- const body = await activityPubContextify(follow, 'Follow')
-
- const httpSignature = {
- algorithm: HTTP_SIGNATURE.ALGORITHM,
- authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
- keyId: by.url,
- key: by.privateKey,
- headers: HTTP_SIGNATURE.HEADERS_TO_SIGN_WITH_PAYLOAD
- }
- const headers = {
- 'digest': buildDigest(body),
- 'content-type': 'application/activity+json',
- 'accept': ACTIVITY_PUB.ACCEPT_HEADER
- }
-
- return makePOSTAPRequest(to.url + '/inbox', body, httpSignature, headers)
-}
-
-describe('Test ActivityPub security', function () {
- let servers: PeerTubeServer[]
- let sqlCommands: SQLCommand[] = []
-
- let url: string
-
- const keys = require(buildAbsoluteFixturePath('./ap-json/peertube/keys.json'))
- const invalidKeys = require(buildAbsoluteFixturePath('./ap-json/peertube/invalid-keys.json'))
- const baseHttpSignature = () => ({
- algorithm: HTTP_SIGNATURE.ALGORITHM,
- authorizationHeaderName: HTTP_SIGNATURE.HEADER_NAME,
- keyId: 'acct:peertube@' + servers[1].host,
- key: keys.privateKey,
- headers: HTTP_SIGNATURE.HEADERS_TO_SIGN_WITH_PAYLOAD
- })
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(3)
-
- sqlCommands = servers.map(s => new SQLCommand(s))
-
- url = servers[0].url + '/inbox'
-
- await setKeysOfServer(sqlCommands[0], servers[1].url, keys.publicKey, null)
- await setKeysOfServer(sqlCommands[1], servers[1].url, keys.publicKey, keys.privateKey)
-
- const to = { url: servers[0].url + '/accounts/peertube' }
- const by = { url: servers[1].url + '/accounts/peertube', privateKey: keys.privateKey }
- await makeFollowRequest(to, by)
- })
-
- describe('When checking HTTP signature', function () {
-
- it('Should fail with an invalid digest', async function () {
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = {
- Digest: buildDigest({ hello: 'coucou' })
- }
-
- try {
- await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
-
- it('Should fail with an invalid date', async function () {
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
- headers['date'] = 'Wed, 21 Oct 2015 07:28:00 GMT'
-
- try {
- await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
-
- it('Should fail with bad keys', async function () {
- await setKeysOfServer(sqlCommands[0], servers[1].url, invalidKeys.publicKey, invalidKeys.privateKey)
- await setKeysOfServer(sqlCommands[1], servers[1].url, invalidKeys.publicKey, invalidKeys.privateKey)
-
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
-
- try {
- await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
-
- it('Should reject requests without appropriate signed headers', async function () {
- await setKeysOfServer(sqlCommands[0], servers[1].url, keys.publicKey, keys.privateKey)
- await setKeysOfServer(sqlCommands[1], servers[1].url, keys.publicKey, keys.privateKey)
-
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
-
- const signatureOptions = baseHttpSignature()
- const badHeadersMatrix = [
- [ '(request-target)', 'date', 'digest' ],
- [ 'host', 'date', 'digest' ],
- [ '(request-target)', 'host', 'digest' ]
- ]
-
- for (const badHeaders of badHeadersMatrix) {
- signatureOptions.headers = badHeaders
-
- try {
- await makePOSTAPRequest(url, body, signatureOptions, headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- }
- })
-
- it('Should succeed with a valid HTTP signature draft 11 (without date but with (created))', async function () {
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
-
- const signatureOptions = baseHttpSignature()
- signatureOptions.headers = [ '(request-target)', '(created)', 'host', 'digest' ]
-
- const { statusCode } = await makePOSTAPRequest(url, body, signatureOptions, headers)
- expect(statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
- })
-
- it('Should succeed with a valid HTTP signature', async function () {
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
-
- const { statusCode } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
- expect(statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
- })
-
- it('Should refresh the actor keys', async function () {
- this.timeout(20000)
-
- // Update keys of server 2 to invalid keys
- // Server 1 should refresh the actor and fail
- await setKeysOfServer(sqlCommands[1], servers[1].url, invalidKeys.publicKey, invalidKeys.privateKey)
- await setUpdatedAtOfServer(sqlCommands[0], servers[1].url, '2015-07-17 22:00:00+00')
-
- // Invalid peertube actor cache
- await killallServers([ servers[1] ])
- await servers[1].run()
-
- const body = await activityPubContextify(getAnnounceWithoutContext(servers[1]), 'Announce')
- const headers = buildGlobalHeaders(body)
-
- try {
- await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- console.error(err)
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
- })
-
- describe('When checking Linked Data Signature', function () {
- before(async function () {
- await setKeysOfServer(sqlCommands[0], servers[1].url, keys.publicKey, keys.privateKey)
- await setKeysOfServer(sqlCommands[1], servers[1].url, keys.publicKey, keys.privateKey)
- await setKeysOfServer(sqlCommands[2], servers[2].url, keys.publicKey, keys.privateKey)
-
- const to = { url: servers[0].url + '/accounts/peertube' }
- const by = { url: servers[2].url + '/accounts/peertube', privateKey: keys.privateKey }
- await makeFollowRequest(to, by)
- })
-
- it('Should fail with bad keys', async function () {
- await setKeysOfServer(sqlCommands[0], servers[2].url, invalidKeys.publicKey, invalidKeys.privateKey)
- await setKeysOfServer(sqlCommands[2], servers[2].url, invalidKeys.publicKey, invalidKeys.privateKey)
-
- const body = getAnnounceWithoutContext(servers[1])
- body.actor = servers[2].url + '/accounts/peertube'
-
- const signer: any = { privateKey: invalidKeys.privateKey, url: servers[2].url + '/accounts/peertube' }
- const signedBody = await signAndContextify(signer, body, 'Announce')
-
- const headers = buildGlobalHeaders(signedBody)
-
- try {
- await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
-
- it('Should fail with an altered body', async function () {
- await setKeysOfServer(sqlCommands[0], servers[2].url, keys.publicKey, keys.privateKey)
- await setKeysOfServer(sqlCommands[0], servers[2].url, keys.publicKey, keys.privateKey)
-
- const body = getAnnounceWithoutContext(servers[1])
- body.actor = servers[2].url + '/accounts/peertube'
-
- const signer: any = { privateKey: keys.privateKey, url: servers[2].url + '/accounts/peertube' }
- const signedBody = await signAndContextify(signer, body, 'Announce')
-
- signedBody.actor = servers[2].url + '/account/peertube'
-
- const headers = buildGlobalHeaders(signedBody)
-
- try {
- await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
-
- it('Should succeed with a valid signature', async function () {
- const body = getAnnounceWithoutContext(servers[1])
- body.actor = servers[2].url + '/accounts/peertube'
-
- const signer: any = { privateKey: keys.privateKey, url: servers[2].url + '/accounts/peertube' }
- const signedBody = await signAndContextify(signer, body, 'Announce')
-
- const headers = buildGlobalHeaders(signedBody)
-
- const { statusCode } = await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
- expect(statusCode).to.equal(HttpStatusCode.NO_CONTENT_204)
- })
-
- it('Should refresh the actor keys', async function () {
- this.timeout(20000)
-
- // Wait refresh invalidation
- await wait(10000)
-
- // Update keys of server 3 to invalid keys
- // Server 1 should refresh the actor and fail
- await setKeysOfServer(sqlCommands[2], servers[2].url, invalidKeys.publicKey, invalidKeys.privateKey)
-
- const body = getAnnounceWithoutContext(servers[1])
- body.actor = servers[2].url + '/accounts/peertube'
-
- const signer: any = { privateKey: keys.privateKey, url: servers[2].url + '/accounts/peertube' }
- const signedBody = await signAndContextify(signer, body, 'Announce')
-
- const headers = buildGlobalHeaders(signedBody)
-
- try {
- await makePOSTAPRequest(url, signedBody, baseHttpSignature(), headers)
- expect(true, 'Did not throw').to.be.false
- } catch (err) {
- expect(err.statusCode).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
- })
- })
-
- after(async function () {
- for (const sql of sqlCommands) {
- await sql.cleanup()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/abuses.ts b/server/tests/api/check-params/abuses.ts
deleted file mode 100644
index 331d3f8f7..000000000
--- a/server/tests/api/check-params/abuses.ts
+++ /dev/null
@@ -1,438 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { AbuseCreate, AbuseState, HttpStatusCode } from '@shared/models'
-import {
- AbusesCommand,
- cleanupTests,
- createSingleServer,
- doubleFollow,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test abuses API validators', function () {
- const basePath = '/api/v1/abuses/'
-
- let server: PeerTubeServer
-
- let userToken = ''
- let userToken2 = ''
- let abuseId: number
- let messageId: number
-
- let command: AbusesCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- userToken = await server.users.generateUserAndToken('user_1')
- userToken2 = await server.users.generateUserAndToken('user_2')
-
- server.store.videoCreated = await server.videos.upload()
-
- command = server.abuses
- })
-
- describe('When listing abuses for admins', function () {
- const path = basePath
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a bad id filter', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { id: 'toto' } })
- })
-
- it('Should fail with a bad filter', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { filter: 'toto' } })
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { filter: 'videos' } })
- })
-
- it('Should fail with bad predefined reason', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { predefinedReason: 'violentOrRepulsives' } })
- })
-
- it('Should fail with a bad state filter', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { state: 'toto' } })
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { state: 0 } })
- })
-
- it('Should fail with a bad videoIs filter', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { videoIs: 'toto' } })
- })
-
- it('Should succeed with the correct params', async function () {
- const query = {
- id: 13,
- predefinedReason: 'violentOrRepulsive',
- filter: 'comment',
- state: 2,
- videoIs: 'deleted'
- }
-
- await makeGetRequest({ url: server.url, path, token: server.accessToken, query, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When listing abuses for users', function () {
- const path = '/api/v1/users/me/abuses'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, userToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, userToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, userToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad id filter', async function () {
- await makeGetRequest({ url: server.url, path, token: userToken, query: { id: 'toto' } })
- })
-
- it('Should fail with a bad state filter', async function () {
- await makeGetRequest({ url: server.url, path, token: userToken, query: { state: 'toto' } })
- await makeGetRequest({ url: server.url, path, token: userToken, query: { state: 0 } })
- })
-
- it('Should succeed with the correct params', async function () {
- const query = {
- id: 13,
- state: 2
- }
-
- await makeGetRequest({ url: server.url, path, token: userToken, query, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When reporting an abuse', function () {
- const path = basePath
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with a wrong video', async function () {
- const fields = { video: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with an unknown video', async function () {
- const fields = { video: { id: 42 }, reason: 'my super reason' }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a wrong comment', async function () {
- const fields = { comment: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with an unknown comment', async function () {
- const fields = { comment: { id: 42 }, reason: 'my super reason' }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a wrong account', async function () {
- const fields = { account: { id: 'blabla' }, reason: 'my super reason' }
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with an unknown account', async function () {
- const fields = { account: { id: 42 }, reason: 'my super reason' }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with not account, comment or video', async function () {
- const fields = { reason: 'my super reason' }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a non authenticated user', async function () {
- const fields = { video: { id: server.store.videoCreated.id }, reason: 'my super reason' }
-
- await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a reason too short', async function () {
- const fields = { video: { id: server.store.videoCreated.id }, reason: 'h' }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with a too big reason', async function () {
- const fields = { video: { id: server.store.videoCreated.id }, reason: 'super'.repeat(605) }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should succeed with the correct parameters (basic)', async function () {
- const fields: AbuseCreate = { video: { id: server.store.videoCreated.shortUUID }, reason: 'my super reason' }
-
- const res = await makePostBodyRequest({
- url: server.url,
- path,
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- abuseId = res.body.abuse.id
- })
-
- it('Should fail with a wrong predefined reason', async function () {
- const fields = { video: server.store.videoCreated, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail with negative timestamps', async function () {
- const fields = { video: { id: server.store.videoCreated.id, startAt: -1 }, reason: 'my super reason' }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should fail mith misordered startAt/endAt', async function () {
- const fields = { video: { id: server.store.videoCreated.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields })
- })
-
- it('Should succeed with the correct parameters (advanced)', async function () {
- const fields: AbuseCreate = {
- video: {
- id: server.store.videoCreated.id,
- startAt: 1,
- endAt: 5
- },
- reason: 'my super reason',
- predefinedReasons: [ 'serverRules' ]
- }
-
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When updating an abuse', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await command.update({ token: 'blabla', abuseId, body: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a non admin user', async function () {
- await command.update({ token: userToken, abuseId, body: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad abuse id', async function () {
- await command.update({ abuseId: 45, body: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a bad state', async function () {
- const body = { state: 5 }
- await command.update({ abuseId, body, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad moderation comment', async function () {
- const body = { moderationComment: 'b'.repeat(3001) }
- await command.update({ abuseId, body, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct params', async function () {
- const body = { state: AbuseState.ACCEPTED }
- await command.update({ abuseId, body })
- })
- })
-
- describe('When creating an abuse message', function () {
- const message = 'my super message'
-
- it('Should fail with an invalid abuse id', async function () {
- await command.addMessage({ token: userToken2, abuseId: 888, message, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non authenticated user', async function () {
- await command.addMessage({ token: 'fake_token', abuseId, message, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with an invalid logged in user', async function () {
- await command.addMessage({ token: userToken2, abuseId, message, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with an invalid message', async function () {
- await command.addMessage({ token: userToken, abuseId, message: 'a'.repeat(5000), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct params', async function () {
- const res = await command.addMessage({ token: userToken, abuseId, message })
- messageId = res.body.abuseMessage.id
- })
- })
-
- describe('When listing abuse messages', function () {
-
- it('Should fail with an invalid abuse id', async function () {
- await command.listMessages({ token: userToken, abuseId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non authenticated user', async function () {
- await command.listMessages({ token: 'fake_token', abuseId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with an invalid logged in user', async function () {
- await command.listMessages({ token: userToken2, abuseId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.listMessages({ token: userToken, abuseId })
- })
- })
-
- describe('When deleting an abuse message', function () {
- it('Should fail with an invalid abuse id', async function () {
- await command.deleteMessage({ token: userToken, abuseId: 888, messageId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an invalid message id', async function () {
- await command.deleteMessage({ token: userToken, abuseId, messageId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non authenticated user', async function () {
- await command.deleteMessage({ token: 'fake_token', abuseId, messageId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with an invalid logged in user', async function () {
- await command.deleteMessage({ token: userToken2, abuseId, messageId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.deleteMessage({ token: userToken, abuseId, messageId })
- })
- })
-
- describe('When deleting a video abuse', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await command.delete({ token: 'blabla', abuseId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a non admin user', async function () {
- await command.delete({ token: userToken, abuseId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad abuse id', async function () {
- await command.delete({ abuseId: 45, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.delete({ abuseId })
- })
- })
-
- describe('When trying to manage messages of a remote abuse', function () {
- let remoteAbuseId: number
- let anotherServer: PeerTubeServer
-
- before(async function () {
- this.timeout(50000)
-
- anotherServer = await createSingleServer(2)
- await setAccessTokensToServers([ anotherServer ])
-
- await doubleFollow(anotherServer, server)
-
- const server2VideoId = await anotherServer.videos.getId({ uuid: server.store.videoCreated.uuid })
- await anotherServer.abuses.report({ reason: 'remote server', videoId: server2VideoId })
-
- await waitJobs([ server, anotherServer ])
-
- const body = await command.getAdminList({ sort: '-createdAt' })
- remoteAbuseId = body.data[0].id
- })
-
- it('Should fail when listing abuse messages of a remote abuse', async function () {
- await command.listMessages({ abuseId: remoteAbuseId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail when creating abuse message of a remote abuse', async function () {
- await command.addMessage({ abuseId: remoteAbuseId, message: 'message', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- after(async function () {
- await cleanupTests([ anotherServer ])
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/accounts.ts b/server/tests/api/check-params/accounts.ts
deleted file mode 100644
index afc0049ff..000000000
--- a/server/tests/api/check-params/accounts.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/server-commands'
-
-describe('Test accounts API validators', function () {
- const path = '/api/v1/accounts/'
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- })
-
- describe('When listing accounts', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
- })
-
- describe('When getting an account', function () {
-
- it('Should return 404 with a non existing name', async function () {
- await server.accounts.get({ accountName: 'arfaze', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/blocklist.ts b/server/tests/api/check-params/blocklist.ts
deleted file mode 100644
index 169b591a3..000000000
--- a/server/tests/api/check-params/blocklist.ts
+++ /dev/null
@@ -1,556 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test blocklist API validators', function () {
- let servers: PeerTubeServer[]
- let server: PeerTubeServer
- let userAccessToken: string
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- server = servers[0]
-
- const user = { username: 'user1', password: 'password' }
- await server.users.create({ username: user.username, password: user.password })
-
- userAccessToken = await server.login.getAccessToken(user)
-
- await doubleFollow(servers[0], servers[1])
- })
-
- // ---------------------------------------------------------------
-
- describe('When managing user blocklist', function () {
-
- describe('When managing user accounts blocklist', function () {
- const path = '/api/v1/users/me/blocklist/accounts'
-
- describe('When listing blocked accounts', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
- })
-
- describe('When blocking an account', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { accountName: 'user1' },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with an unknown account', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user2' },
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail to block ourselves', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'root' },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user1' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When unblocking an account', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with an unknown account block', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user2',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
- })
-
- describe('When managing user servers blocklist', function () {
- const path = '/api/v1/users/me/blocklist/servers'
-
- describe('When listing blocked servers', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
- })
-
- describe('When blocking a server', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { host: '127.0.0.1:9002' },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with an unknown server', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: '127.0.0.1:9003' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should fail with our own server', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: server.host },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: servers[1].host },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When unblocking a server', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/' + servers[1].host,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with an unknown server block', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/127.0.0.1:9004',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/' + servers[1].host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
- })
- })
-
- describe('When managing server blocklist', function () {
-
- describe('When managing server accounts blocklist', function () {
- const path = '/api/v1/server/blocklist/accounts'
-
- describe('When listing blocked accounts', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makeGetRequest({
- url: server.url,
- token: userAccessToken,
- path,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
- })
-
- describe('When blocking an account', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { accountName: 'user1' },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: userAccessToken,
- path,
- fields: { accountName: 'user1' },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an unknown account', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user2' },
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail to block ourselves', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'root' },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user1' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When unblocking an account', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1',
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an unknown account block', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user2',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
- })
-
- describe('When managing server servers blocklist', function () {
- const path = '/api/v1/server/blocklist/servers'
-
- describe('When listing blocked servers', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makeGetRequest({
- url: server.url,
- token: userAccessToken,
- path,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
- })
-
- describe('When blocking a server', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { host: servers[1].host },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: userAccessToken,
- path,
- fields: { host: servers[1].host },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with an unknown server', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: '127.0.0.1:9003' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should fail with our own server', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: server.host },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { host: servers[1].host },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When unblocking a server', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/' + servers[1].host,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a user without the appropriate rights', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/' + servers[1].host,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an unknown server block', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/127.0.0.1:9004',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/' + servers[1].host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
- })
- })
-
- describe('When getting blocklist status', function () {
- const path = '/api/v1/blocklist/status'
-
- it('Should fail with a bad token', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: 'false',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad accounts field', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- accounts: 1
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- accounts: [ 1 ]
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad hosts field', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- hosts: 1
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- hosts: [ 1 ]
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {},
- expectedStatus: HttpStatusCode.OK_200
- })
-
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- hosts: [ 'example.com' ],
- accounts: [ 'john@example.com' ]
- },
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/bulk.ts b/server/tests/api/check-params/bulk.ts
deleted file mode 100644
index f03264b4f..000000000
--- a/server/tests/api/check-params/bulk.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Test bulk API validators', function () {
- let server: PeerTubeServer
- let userAccessToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- const user = { username: 'user1', password: 'password' }
- await server.users.create({ username: user.username, password: user.password })
-
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When removing comments of', function () {
- const path = '/api/v1/bulk/remove-comments-of'
-
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { accountName: 'user1', scope: 'my-videos' },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with an unknown account', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user2', scope: 'my-videos' },
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an invalid scope', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user1', scope: 'my-videoss' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to delete comments of the instance without the appropriate rights', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: userAccessToken,
- path,
- fields: { accountName: 'user1', scope: 'instance' },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path,
- fields: { accountName: 'user1', scope: 'instance' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/channel-import-videos.ts b/server/tests/api/check-params/channel-import-videos.ts
deleted file mode 100644
index 2de13b629..000000000
--- a/server/tests/api/check-params/channel-import-videos.ts
+++ /dev/null
@@ -1,209 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { areHttpImportTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import {
- ChannelsCommand,
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test videos import in a channel API validator', function () {
- let server: PeerTubeServer
- const userInfo = {
- accessToken: '',
- channelName: 'fake_channel',
- channelId: -1,
- id: -1,
- videoQuota: -1,
- videoQuotaDaily: -1,
- channelSyncId: -1
- }
- let command: ChannelsCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableImports()
- await server.config.enableChannelSync()
-
- const userCreds = {
- username: 'fake',
- password: 'fake_password'
- }
-
- {
- const user = await server.users.create({ username: userCreds.username, password: userCreds.password })
- userInfo.id = user.id
- userInfo.accessToken = await server.login.getAccessToken(userCreds)
-
- const info = await server.users.getMyInfo({ token: userInfo.accessToken })
- userInfo.channelId = info.videoChannels[0].id
- }
-
- {
- const { videoChannelSync } = await server.channelSyncs.create({
- token: userInfo.accessToken,
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: userInfo.channelId
- }
- })
- userInfo.channelSyncId = videoChannelSync.id
- }
-
- command = server.channels
- })
-
- it('Should fail when HTTP upload is disabled', async function () {
- await server.config.disableChannelSync()
- await server.config.disableImports()
-
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
-
- await server.config.enableImports()
- })
-
- it('Should fail when externalChannelUrl is not provided', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: null,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail when externalChannelUrl is malformed', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: 'not-a-url',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad sync id', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelSyncId: 'toto' as any,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a unknown sync id', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelSyncId: 42,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a sync id of another channel', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelSyncId: userInfo.channelSyncId,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with no authentication', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail when sync is not owned by the user', async function () {
- await command.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: userInfo.accessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail when the user has no quota', async function () {
- await server.users.update({
- userId: userInfo.id,
- videoQuota: 0
- })
-
- await command.importVideos({
- channelName: 'fake_channel',
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: userInfo.accessToken,
- expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413
- })
-
- await server.users.update({
- userId: userInfo.id,
- videoQuota: userInfo.videoQuota
- })
- })
-
- it('Should fail when the user has no daily quota', async function () {
- await server.users.update({
- userId: userInfo.id,
- videoQuotaDaily: 0
- })
-
- await command.importVideos({
- channelName: 'fake_channel',
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: userInfo.accessToken,
- expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413
- })
-
- await server.users.update({
- userId: userInfo.id,
- videoQuotaDaily: userInfo.videoQuotaDaily
- })
- })
-
- it('Should succeed when sync is run by its owner', async function () {
- if (!areHttpImportTestsDisabled()) return
-
- await command.importVideos({
- channelName: 'fake_channel',
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- token: userInfo.accessToken
- })
- })
-
- it('Should succeed when sync is run with root and for another user\'s channel', async function () {
- if (!areHttpImportTestsDisabled()) return
-
- await command.importVideos({
- channelName: 'fake_channel',
- externalChannelUrl: FIXTURE_URLS.youtubeChannel
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
deleted file mode 100644
index 2f523d4ce..000000000
--- a/server/tests/api/check-params/config.ts
+++ /dev/null
@@ -1,428 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { merge } from 'lodash'
-import { omit } from '@shared/core-utils'
-import { CustomConfig, HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test config API validators', function () {
- const path = '/api/v1/config/custom'
- let server: PeerTubeServer
- let userAccessToken: string
- const updateParams: CustomConfig = {
- instance: {
- name: 'PeerTube updated',
- shortDescription: 'my short description',
- description: 'my super description',
- terms: 'my super terms',
- codeOfConduct: 'my super coc',
-
- creationReason: 'my super reason',
- moderationInformation: 'my super moderation information',
- administrator: 'Kuja',
- maintenanceLifetime: 'forever',
- businessModel: 'my super business model',
- hardwareInformation: '2vCore 3GB RAM',
-
- languages: [ 'en', 'es' ],
- categories: [ 1, 2 ],
-
- isNSFW: true,
- defaultNSFWPolicy: 'blur',
-
- defaultClientRoute: '/videos/recently-added',
-
- customizations: {
- javascript: 'alert("coucou")',
- css: 'body { background-color: red; }'
- }
- },
- theme: {
- default: 'default'
- },
- services: {
- twitter: {
- username: '@MySuperUsername',
- whitelisted: true
- }
- },
- client: {
- videos: {
- miniature: {
- preferAuthorDisplayName: false
- }
- },
- menu: {
- login: {
- redirectOnSingleExternalAuth: false
- }
- }
- },
- cache: {
- previews: {
- size: 2
- },
- captions: {
- size: 3
- },
- torrents: {
- size: 4
- },
- storyboards: {
- size: 5
- }
- },
- signup: {
- enabled: false,
- limit: 5,
- requiresApproval: false,
- requiresEmailVerification: false,
- minimumAge: 16
- },
- admin: {
- email: 'superadmin1@example.com'
- },
- contactForm: {
- enabled: false
- },
- user: {
- history: {
- videos: {
- enabled: true
- }
- },
- videoQuota: 5242881,
- videoQuotaDaily: 318742
- },
- videoChannels: {
- maxPerUser: 20
- },
- transcoding: {
- enabled: true,
- remoteRunners: {
- enabled: true
- },
- allowAdditionalExtensions: true,
- allowAudioFiles: true,
- concurrency: 1,
- threads: 1,
- profile: 'vod_profile',
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': false,
- '360p': true,
- '480p': true,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- alwaysTranscodeOriginalResolution: false,
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: false
- }
- },
- live: {
- enabled: true,
-
- allowReplay: false,
- latencySetting: {
- enabled: false
- },
- maxDuration: 30,
- maxInstanceLives: -1,
- maxUserLives: 50,
-
- transcoding: {
- enabled: true,
- remoteRunners: {
- enabled: true
- },
- threads: 4,
- profile: 'live_profile',
- resolutions: {
- '144p': true,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- alwaysTranscodeOriginalResolution: false
- }
- },
- videoStudio: {
- enabled: true,
- remoteRunners: {
- enabled: true
- }
- },
- videoFile: {
- update: {
- enabled: true
- }
- },
- import: {
- videos: {
- concurrency: 1,
- http: {
- enabled: false
- },
- torrent: {
- enabled: false
- }
- },
- videoChannelSynchronization: {
- enabled: false,
- maxPerUser: 10
- }
- },
- trending: {
- videos: {
- algorithms: {
- enabled: [ 'hot', 'most-viewed', 'most-liked' ],
- default: 'most-viewed'
- }
- }
- },
- autoBlacklist: {
- videos: {
- ofUsers: {
- enabled: false
- }
- }
- },
- followers: {
- instance: {
- enabled: false,
- manualApproval: true
- }
- },
- followings: {
- instance: {
- autoFollowBack: {
- enabled: true
- },
- autoFollowIndex: {
- enabled: true,
- indexUrl: 'https://index.example.com'
- }
- }
- },
- broadcastMessage: {
- enabled: true,
- dismissable: true,
- message: 'super message',
- level: 'warning'
- },
- search: {
- remoteUri: {
- users: true,
- anonymous: true
- },
- searchIndex: {
- enabled: true,
- url: 'https://search.joinpeertube.org',
- disableLocalSearch: true,
- isDefaultSearch: true
- }
- }
- }
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When getting the configuration', function () {
- it('Should fail without token', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- describe('When updating the configuration', function () {
- it('Should fail without token', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: updateParams,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: updateParams,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail if it misses a key', async function () {
- const newUpdateParams = { ...updateParams, admin: omit(updateParams.admin, [ 'email' ]) }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: newUpdateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad default NSFW policy', async function () {
- const newUpdateParams = {
- ...updateParams,
-
- instance: {
- defaultNSFWPolicy: 'hello'
- }
- }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: newUpdateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if email disabled and signup requires email verification', async function () {
- // opposite scenario - success when enable enabled - covered via tests/api/users/user-verification.ts
- const newUpdateParams = {
- ...updateParams,
-
- signup: {
- enabled: true,
- limit: 5,
- requiresApproval: true,
- requiresEmailVerification: true
- }
- }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: newUpdateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a disabled web videos & hls transcoding', async function () {
- const newUpdateParams = {
- ...updateParams,
-
- transcoding: {
- hls: {
- enabled: false
- },
- web_videos: {
- enabled: false
- }
- }
- }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: newUpdateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a disabled http upload & enabled sync', async function () {
- const newUpdateParams: CustomConfig = merge({}, updateParams, {
- import: {
- videos: {
- http: { enabled: false }
- },
- videoChannelSynchronization: { enabled: true }
- }
- })
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: newUpdateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: updateParams,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When deleting the configuration', function () {
- it('Should fail without token', async function () {
- await makeDeleteRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeDeleteRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts
deleted file mode 100644
index f0f8819b9..000000000
--- a/server/tests/api/check-params/contact-form.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { MockSmtpServer } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- ContactFormCommand,
- createSingleServer,
- killallServers,
- PeerTubeServer
-} from '@shared/server-commands'
-
-describe('Test contact form API validators', function () {
- let server: PeerTubeServer
- const emails: object[] = []
- const defaultBody = {
- fromName: 'super name',
- fromEmail: 'toto@example.com',
- subject: 'my subject',
- body: 'Hello, how are you?'
- }
- let emailPort: number
- let command: ContactFormCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(60000)
-
- emailPort = await MockSmtpServer.Instance.collectEmails(emails)
-
- // Email is disabled
- server = await createSingleServer(1)
- command = server.contactForm
- })
-
- it('Should not accept a contact form if emails are disabled', async function () {
- await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should not accept a contact form if it is disabled in the configuration', async function () {
- this.timeout(25000)
-
- await killallServers([ server ])
-
- // Contact form is disabled
- await server.run({ ...ConfigCommand.getEmailOverrideConfig(emailPort), contact_form: { enabled: false } })
- await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should not accept a contact form if from email is invalid', async function () {
- this.timeout(25000)
-
- await killallServers([ server ])
-
- // Email & contact form enabled
- await server.run(ConfigCommand.getEmailOverrideConfig(emailPort))
-
- await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, fromEmail: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not accept a contact form if from name is invalid', async function () {
- await command.send({ ...defaultBody, fromName: 'name'.repeat(100), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, fromName: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, fromName: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not accept a contact form if body is invalid', async function () {
- await command.send({ ...defaultBody, body: 'body'.repeat(5000), expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, body: 'a', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.send({ ...defaultBody, body: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should accept a contact form with the correct parameters', async function () {
- await command.send(defaultBody)
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/custom-pages.ts b/server/tests/api/check-params/custom-pages.ts
deleted file mode 100644
index 63e3da3d5..000000000
--- a/server/tests/api/check-params/custom-pages.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test custom pages validators', function () {
- const path = '/api/v1/custom-pages/homepage/instance'
-
- let server: PeerTubeServer
- let userAccessToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- const user = { username: 'user1', password: 'password' }
- await server.users.create({ username: user.username, password: user.password })
-
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When updating instance homepage', function () {
-
- it('Should fail with an unauthenticated user', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: { content: 'super content' },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: userAccessToken,
- fields: { content: 'super content' },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { content: 'super content' },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When getting instance homapage', function () {
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/debug.ts b/server/tests/api/check-params/debug.ts
deleted file mode 100644
index d7b68f163..000000000
--- a/server/tests/api/check-params/debug.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Test debug API validators', function () {
- const path = '/api/v1/server/debug'
- let server: PeerTubeServer
- let userAccessToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When getting debug endpoint', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: { startDate: new Date().toISOString() },
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/follows.ts b/server/tests/api/check-params/follows.ts
deleted file mode 100644
index 3c911dcee..000000000
--- a/server/tests/api/check-params/follows.ts
+++ /dev/null
@@ -1,369 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test server follows API validators', function () {
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- })
-
- describe('When managing following', function () {
- let userAccessToken = null
-
- before(async function () {
- userAccessToken = await server.users.generateUserAndToken('user1')
- })
-
- describe('When adding follows', function () {
- const path = '/api/v1/server/following'
-
- it('Should fail with nothing', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if hosts is not composed by hosts', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { hosts: [ '127.0.0.1:9002', '127.0.0.1:coucou' ] },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if hosts is composed with http schemes', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { hosts: [ '127.0.0.1:9002', 'http://127.0.0.1:9003' ] },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if hosts are not unique', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { urls: [ '127.0.0.1:9002', '127.0.0.1:9002' ] },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if handles is not composed by handles', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { handles: [ 'hello@example.com', '127.0.0.1:9001' ] },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if handles are not unique', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { urls: [ 'hello@example.com', 'hello@example.com' ] },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an invalid token', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { hosts: [ '127.0.0.1:9002' ] },
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { hosts: [ '127.0.0.1:9002' ] },
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- describe('When listing followings', function () {
- const path = '/api/v1/server/following'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path)
- })
-
- it('Should fail with an incorrect state', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- state: 'blabla'
- }
- })
- })
-
- it('Should fail with an incorrect actor type', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- actorType: 'blabla'
- }
- })
- })
-
- it('Should fail succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.OK_200,
- query: {
- state: 'accepted',
- actorType: 'Application'
- }
- })
- })
- })
-
- describe('When listing followers', function () {
- const path = '/api/v1/server/followers'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path)
- })
-
- it('Should fail with an incorrect actor type', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- actorType: 'blabla'
- }
- })
- })
-
- it('Should fail with an incorrect state', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- state: 'blabla',
- actorType: 'Application'
- }
- })
- })
-
- it('Should fail succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.OK_200,
- query: {
- state: 'accepted'
- }
- })
- })
- })
-
- describe('When removing a follower', function () {
- const path = '/api/v1/server/followers'
-
- it('Should fail with an invalid token', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002',
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002',
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid follower', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/toto',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown follower', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9003',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- })
-
- describe('When accepting a follower', function () {
- const path = '/api/v1/server/followers'
-
- it('Should fail with an invalid token', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002/accept',
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002/accept',
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid follower', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto/accept',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown follower', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9003/accept',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- })
-
- describe('When rejecting a follower', function () {
- const path = '/api/v1/server/followers'
-
- it('Should fail with an invalid token', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002/reject',
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9002/reject',
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid follower', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto/reject',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown follower', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: path + '/toto@127.0.0.1:9003/reject',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- })
-
- describe('When removing following', function () {
- const path = '/api/v1/server/following'
-
- it('Should fail with an invalid token', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/127.0.0.1:9002',
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/127.0.0.1:9002',
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail if we do not follow this server', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/example.com',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts
deleted file mode 100644
index c2a7ccd78..000000000
--- a/server/tests/api/check-params/index.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import './abuses'
-import './accounts'
-import './blocklist'
-import './bulk'
-import './channel-import-videos'
-import './config'
-import './contact-form'
-import './custom-pages'
-import './debug'
-import './follows'
-import './jobs'
-import './live'
-import './logs'
-import './metrics'
-import './my-user'
-import './plugins'
-import './redundancy'
-import './registrations'
-import './runners'
-import './search'
-import './services'
-import './transcoding'
-import './two-factor'
-import './upload-quota'
-import './user-notifications'
-import './user-subscriptions'
-import './users-admin'
-import './users-emails'
-import './video-blacklist'
-import './video-captions'
-import './video-channel-syncs'
-import './video-channels'
-import './video-comments'
-import './video-files'
-import './video-imports'
-import './video-playlists'
-import './video-storyboards'
-import './video-source'
-import './video-studio'
-import './video-token'
-import './videos-common-filters'
-import './videos-history'
-import './videos-overviews'
-import './videos'
-import './views'
diff --git a/server/tests/api/check-params/jobs.ts b/server/tests/api/check-params/jobs.ts
deleted file mode 100644
index 873da3955..000000000
--- a/server/tests/api/check-params/jobs.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test jobs API validators', function () {
- const path = '/api/v1/jobs/failed'
- let server: PeerTubeServer
- let userAccessToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When listing jobs', function () {
-
- it('Should fail with a bad state', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path: path + 'ade'
- })
- })
-
- it('Should fail with an incorrect job type', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: {
- jobType: 'toto'
- }
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- describe('When pausing/resuming the job queue', async function () {
- const commands = [ 'pause', 'resume' ]
-
- it('Should fail with a non authenticated user', async function () {
- for (const command of commands) {
- await makePostBodyRequest({
- url: server.url,
- path: '/api/v1/jobs/' + command,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- }
- })
-
- it('Should fail with a non admin user', async function () {
- for (const command of commands) {
- await makePostBodyRequest({
- url: server.url,
- path: '/api/v1/jobs/' + command,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- }
- })
-
- it('Should succeed with the correct params', async function () {
- for (const command of commands) {
- await makePostBodyRequest({
- url: server.url,
- path: '/api/v1/jobs/' + command,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- }
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts
deleted file mode 100644
index 5021db516..000000000
--- a/server/tests/api/check-params/live.ts
+++ /dev/null
@@ -1,589 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { buildAbsoluteFixturePath, omit } from '@shared/core-utils'
-import { HttpStatusCode, LiveVideoLatencyMode, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- LiveCommand,
- makePostBodyRequest,
- makeUploadRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- stopFfmpeg
-} from '@shared/server-commands'
-
-describe('Test video lives API validator', function () {
- const path = '/api/v1/videos/live'
- let server: PeerTubeServer
- let userAccessToken = ''
- let channelId: number
- let video: VideoCreateResult
- let videoIdNotLive: number
- let command: LiveCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- latencySetting: {
- enabled: false
- },
- maxInstanceLives: 20,
- maxUserLives: 20,
- allowReplay: true
- }
- }
- })
-
- const username = 'user1'
- const password = 'my super password'
- await server.users.create({ username, password })
- userAccessToken = await server.login.getAccessToken({ username, password })
-
- {
- const { videoChannels } = await server.users.getMyInfo()
- channelId = videoChannels[0].id
- }
-
- {
- videoIdNotLive = (await server.videos.quickUpload({ name: 'not live' })).id
- }
-
- command = server.live
- })
-
- describe('When creating a live', function () {
- let baseCorrectParams
-
- before(function () {
- baseCorrectParams = {
- name: 'my super name',
- category: 5,
- licence: 1,
- language: 'pt',
- nsfw: false,
- commentsEnabled: true,
- downloadEnabled: true,
- waitTranscoding: true,
- description: 'my super description',
- support: 'my super support text',
- tags: [ 'tag1', 'tag2' ],
- privacy: VideoPrivacy.PUBLIC,
- channelId,
- saveReplay: false,
- replaySettings: undefined,
- permanentLive: false,
- latencyMode: LiveVideoLatencyMode.DEFAULT
- }
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad category', async function () {
- const fields = { ...baseCorrectParams, category: 125 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad licence', async function () {
- const fields = { ...baseCorrectParams, licence: 125 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad language', async function () {
- const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail without a channel', async function () {
- const fields = omit(baseCorrectParams, [ 'channelId' ])
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad channel', async function () {
- const fields = { ...baseCorrectParams, channelId: 545454 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad privacy for replay settings', async function () {
- const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: 999 } }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with another user channel', async function () {
- const user = {
- username: 'fake',
- password: 'fake_password'
- }
- await server.users.create({ username: user.username, password: user.password })
-
- const accessTokenUser = await server.login.getAccessToken(user)
- const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
- const customChannelId = videoChannels[0].id
-
- const fields = { ...baseCorrectParams, channelId: customChannelId }
-
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
- })
-
- it('Should fail with too many tags', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too low', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too big', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with a big thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: buildAbsoluteFixturePath('custom-preview-big.png')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with an incorrect preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: buildAbsoluteFixturePath('video_short.mp4')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with a big preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: buildAbsoluteFixturePath('custom-preview-big.png')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with bad latency setting', async function () {
- const fields = { ...baseCorrectParams, latencyMode: 42 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail to set latency if the server does not allow it', async function () {
- const fields = { ...baseCorrectParams, latencyMode: LiveVideoLatencyMode.HIGH_LATENCY }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- this.timeout(30000)
-
- const res = await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- video = res.body.video
- })
-
- it('Should forbid if live is disabled', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: false
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should forbid to save replay if not enabled by the admin', async function () {
- const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }
-
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: false
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should allow to save replay if enabled by the admin', async function () {
- const fields = { ...baseCorrectParams, saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } }
-
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should not allow live if max instance lives is reached', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- maxInstanceLives: 1
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should not allow live if max user lives is reached', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- maxInstanceLives: 20,
- maxUserLives: 1
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- describe('When getting live information', function () {
-
- it('Should fail with a bad access token', async function () {
- await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not display private information without access token', async function () {
- const live = await command.get({ token: '', videoId: video.id })
-
- expect(live.rtmpUrl).to.not.exist
- expect(live.streamKey).to.not.exist
- expect(live.latencyMode).to.exist
- })
-
- it('Should not display private information with token of another user', async function () {
- const live = await command.get({ token: userAccessToken, videoId: video.id })
-
- expect(live.rtmpUrl).to.not.exist
- expect(live.streamKey).to.not.exist
- expect(live.latencyMode).to.exist
- })
-
- it('Should display private information with appropriate token', async function () {
- const live = await command.get({ videoId: video.id })
-
- expect(live.rtmpUrl).to.exist
- expect(live.streamKey).to.exist
- expect(live.latencyMode).to.exist
- })
-
- it('Should fail with a bad video id', async function () {
- await command.get({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown video id', async function () {
- await command.get({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non live video', async function () {
- await command.get({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.get({ videoId: video.id })
- await command.get({ videoId: video.uuid })
- await command.get({ videoId: video.shortUUID })
- })
- })
-
- describe('When getting live sessions', function () {
-
- it('Should fail with a bad access token', async function () {
- await command.listSessions({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without token', async function () {
- await command.listSessions({ token: null, videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with the token of another user', async function () {
- await command.listSessions({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad video id', async function () {
- await command.listSessions({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown video id', async function () {
- await command.listSessions({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non live video', async function () {
- await command.listSessions({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.listSessions({ videoId: video.id })
- })
- })
-
- describe('When getting live session of a replay', function () {
-
- it('Should fail with a bad video id', async function () {
- await command.getReplaySession({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown video id', async function () {
- await command.getReplaySession({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non replay video', async function () {
- await command.getReplaySession({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('When updating live information', async function () {
-
- it('Should fail without access token', async function () {
- await command.update({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a bad access token', async function () {
- await command.update({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with access token of another user', async function () {
- await command.update({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad video id', async function () {
- await command.update({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown video id', async function () {
- await command.update({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a non live video', async function () {
- await command.update({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with bad latency setting', async function () {
- const fields = { latencyMode: 42 }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad privacy for replay settings', async function () {
- const fields = { saveReplay: true, replaySettings: { privacy: 999 } }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with save replay enabled but without replay settings', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true
- }
- }
- })
-
- const fields = { saveReplay: true }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with save replay disabled and replay settings', async function () {
- const fields = { saveReplay: false, replaySettings: { privacy: VideoPrivacy.INTERNAL } }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with only replay settings when save replay is disabled', async function () {
- const fields = { replaySettings: { privacy: VideoPrivacy.INTERNAL } }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail to set latency if the server does not allow it', async function () {
- const fields = { latencyMode: LiveVideoLatencyMode.HIGH_LATENCY }
-
- await command.update({ videoId: video.id, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.update({ videoId: video.id, fields: { saveReplay: false } })
- await command.update({ videoId: video.uuid, fields: { saveReplay: false } })
- await command.update({ videoId: video.shortUUID, fields: { saveReplay: false } })
-
- await command.update({ videoId: video.id, fields: { saveReplay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } } })
-
- })
-
- it('Should fail to update replay status if replay is not allowed on the instance', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: false
- }
- }
- })
-
- await command.update({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail to update a live if it has already started', async function () {
- this.timeout(40000)
-
- const live = await command.get({ videoId: video.id })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
-
- await command.waitUntilPublished({ videoId: video.id })
- await command.update({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should fail to change live privacy if it has already started', async function () {
- this.timeout(40000)
-
- const live = await command.get({ videoId: video.id })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
-
- await command.waitUntilPublished({ videoId: video.id })
-
- await server.videos.update({
- id: video.id,
- attributes: { privacy: VideoPrivacy.PUBLIC } // Same privacy, it's fine
- })
-
- await server.videos.update({
- id: video.id,
- attributes: { privacy: VideoPrivacy.UNLISTED },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should fail to stream twice in the save live', async function () {
- this.timeout(40000)
-
- const live = await command.get({ videoId: video.id })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
-
- await command.waitUntilPublished({ videoId: video.id })
-
- await command.runAndTestStreamError({ videoId: video.id, shouldHaveError: true })
-
- await stopFfmpeg(ffmpegCommand)
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/logs.ts b/server/tests/api/check-params/logs.ts
deleted file mode 100644
index 2496cee31..000000000
--- a/server/tests/api/check-params/logs.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test logs API validators', function () {
- const path = '/api/v1/server/logs'
- let server: PeerTubeServer
- let userAccessToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When getting logs', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a missing startDate query', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad startDate query', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: { startDate: 'toto' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad endDate query', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: { startDate: new Date().toISOString(), endDate: 'toto' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad level parameter', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: { startDate: new Date().toISOString(), level: 'toto' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: { startDate: new Date().toISOString() },
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When creating client logs', function () {
- const base = {
- level: 'warn' as 'warn',
- message: 'my super message',
- url: 'https://example.com/toto'
- }
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- it('Should fail with an invalid level', async function () {
- await server.logs.createLogClient({ payload: { ...base, level: '' as any }, expectedStatus })
- await server.logs.createLogClient({ payload: { ...base, level: undefined }, expectedStatus })
- await server.logs.createLogClient({ payload: { ...base, level: 'toto' as any }, expectedStatus })
- })
-
- it('Should fail with an invalid message', async function () {
- await server.logs.createLogClient({ payload: { ...base, message: undefined }, expectedStatus })
- await server.logs.createLogClient({ payload: { ...base, message: '' }, expectedStatus })
- await server.logs.createLogClient({ payload: { ...base, message: 'm'.repeat(2500) }, expectedStatus })
- })
-
- it('Should fail with an invalid url', async function () {
- await server.logs.createLogClient({ payload: { ...base, url: undefined }, expectedStatus })
- await server.logs.createLogClient({ payload: { ...base, url: 'toto' }, expectedStatus })
- })
-
- it('Should fail with an invalid stackTrace', async function () {
- await server.logs.createLogClient({ payload: { ...base, stackTrace: 's'.repeat(20000) }, expectedStatus })
- })
-
- it('Should fail with an invalid userAgent', async function () {
- await server.logs.createLogClient({ payload: { ...base, userAgent: 's'.repeat(500) }, expectedStatus })
- })
-
- it('Should fail with an invalid meta', async function () {
- await server.logs.createLogClient({ payload: { ...base, meta: 's'.repeat(10000) }, expectedStatus })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.logs.createLogClient({ payload: { ...base, stackTrace: 'stackTrace', meta: '{toto}', userAgent: 'userAgent' } })
- })
-
- it('Should rate limit log creation', async function () {
- let fail = false
-
- for (let i = 0; i < 10; i++) {
- try {
- await server.logs.createLogClient({ token: null, payload: base })
- } catch {
- fail = true
- }
- }
-
- expect(fail).to.be.true
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/metrics.ts b/server/tests/api/check-params/metrics.ts
deleted file mode 100644
index 302bef4f5..000000000
--- a/server/tests/api/check-params/metrics.ts
+++ /dev/null
@@ -1,208 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { omit } from '@shared/core-utils'
-import { HttpStatusCode, PlaybackMetricCreate, VideoResolution } from '@shared/models'
-import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test metrics API validators', function () {
- let server: PeerTubeServer
- let videoUUID: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1, {
- open_telemetry: {
- metrics: {
- enabled: true
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
-
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoUUID = uuid
- })
-
- describe('When adding playback metrics', function () {
- const path = '/api/v1/metrics/playback'
- let baseParams: PlaybackMetricCreate
-
- before(function () {
- baseParams = {
- playerMode: 'p2p-media-loader',
- resolution: VideoResolution.H_1080P,
- fps: 30,
- resolutionChanges: 1,
- errors: 2,
- p2pEnabled: true,
- downloadedBytesP2P: 0,
- downloadedBytesHTTP: 0,
- uploadedBytesP2P: 0,
- videoId: videoUUID
- }
- })
-
- it('Should fail with an invalid resolution', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, resolution: 'toto' }
- })
- })
-
- it('Should fail with an invalid fps', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, fps: 'toto' }
- })
- })
-
- it('Should fail with a missing/invalid player mode', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'playerMode' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, playerMode: 'toto' }
- })
- })
-
- it('Should fail with an missing/invalid resolution changes', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'resolutionChanges' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, resolutionChanges: 'toto' }
- })
- })
-
- it('Should fail with an missing/invalid errors', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'errors' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, errors: 'toto' }
- })
- })
-
- it('Should fail with an missing/invalid downloadedBytesP2P', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'downloadedBytesP2P' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, downloadedBytesP2P: 'toto' }
- })
- })
-
- it('Should fail with an missing/invalid downloadedBytesHTTP', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'downloadedBytesHTTP' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, downloadedBytesHTTP: 'toto' }
- })
- })
-
- it('Should fail with an missing/invalid uploadedBytesP2P', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'uploadedBytesP2P' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, uploadedBytesP2P: 'toto' }
- })
- })
-
- it('Should fail with a missing/invalid p2pEnabled', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: omit(baseParams, [ 'p2pEnabled' ])
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, p2pEnabled: 'toto' }
- })
- })
-
- it('Should fail with an invalid totalPeers', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, p2pPeers: 'toto' }
- })
- })
-
- it('Should fail with a bad video id', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, videoId: 'toto' }
- })
- })
-
- it('Should fail with an unknown video', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, videoId: 42 },
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: baseParams,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { ...baseParams, p2pEnabled: false, totalPeers: 32 },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/my-user.ts b/server/tests/api/check-params/my-user.ts
deleted file mode 100644
index 18f32d46b..000000000
--- a/server/tests/api/check-params/my-user.ts
+++ /dev/null
@@ -1,491 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, MockSmtpServer } from '@server/tests/shared'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import { HttpStatusCode, UserRole, VideoCreateResult } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePutBodyRequest,
- makeUploadRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- UsersCommand
-} from '@shared/server-commands'
-
-describe('Test my user API validators', function () {
- const path = '/api/v1/users/'
- let userId: number
- let rootId: number
- let moderatorId: number
- let video: VideoCreateResult
- let server: PeerTubeServer
- let userToken = ''
- let moderatorToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- {
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- }
-
- {
- const result = await server.users.generate('user1')
- userToken = result.token
- userId = result.userId
- }
-
- {
- const result = await server.users.generate('moderator1', UserRole.MODERATOR)
- moderatorToken = result.token
- }
-
- {
- const result = await server.users.generate('moderator2', UserRole.MODERATOR)
- moderatorId = result.userId
- }
-
- {
- video = await server.videos.upload()
- }
- })
-
- describe('When updating my account', function () {
-
- it('Should fail with an invalid email attribute', async function () {
- const fields = {
- email: 'blabla'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
- })
-
- it('Should fail with a too small password', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'bla'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with a too long password', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'super'.repeat(61)
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail without the current password', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'super'.repeat(61)
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an invalid current password', async function () {
- const fields = {
- currentPassword: 'my super password fail',
- password: 'super'.repeat(61)
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + 'me',
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with an invalid NSFW policy attribute', async function () {
- const fields = {
- nsfwPolicy: 'hello'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an invalid autoPlayVideo attribute', async function () {
- const fields = {
- autoPlayVideo: -1
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
- const fields = {
- autoPlayNextVideo: -1
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
- const fields = {
- videosHistoryEnabled: -1
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an non authenticated user', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'my super password'
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + 'me',
- token: 'super token',
- fields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a too long description', async function () {
- const fields = {
- description: 'super'.repeat(201)
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an invalid videoLanguages attribute', async function () {
- {
- const fields = {
- videoLanguages: 'toto'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- }
-
- {
- const languages = []
- for (let i = 0; i < 1000; i++) {
- languages.push('fr')
- }
-
- const fields = {
- videoLanguages: languages
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- }
- })
-
- it('Should fail with an invalid theme', async function () {
- const fields = { theme: 'invalid' }
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with an unknown theme', async function () {
- const fields = { theme: 'peertube-theme-unknown' }
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- })
-
- it('Should fail with invalid no modal attributes', async function () {
- const keys = [
- 'noInstanceConfigWarningModal',
- 'noAccountSetupWarningModal',
- 'noWelcomeModal'
- ]
-
- for (const key of keys) {
- const fields = {
- [key]: -1
- }
-
- await makePutBodyRequest({ url: server.url, path: path + 'me', token: userToken, fields })
- }
- })
-
- it('Should succeed to change password with the correct params', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'my super password',
- nsfwPolicy: 'blur',
- autoPlayVideo: false,
- email: 'super_email@example.com',
- theme: 'default',
- noInstanceConfigWarningModal: true,
- noWelcomeModal: true,
- noAccountSetupWarningModal: true
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + 'me',
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should succeed without password change with the correct params', async function () {
- const fields = {
- nsfwPolicy: 'blur',
- autoPlayVideo: false
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + 'me',
- token: userToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When updating my avatar', function () {
- it('Should fail without an incorrect input file', async function () {
- const fields = {}
- const attaches = {
- avatarfile: buildAbsoluteFixturePath('video_short.mp4')
- }
- await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with a big file', async function () {
- const fields = {}
- const attaches = {
- avatarfile: buildAbsoluteFixturePath('avatar-big.png')
- }
- await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with an unauthenticated user', async function () {
- const fields = {}
- const attaches = {
- avatarfile: buildAbsoluteFixturePath('avatar.png')
- }
- await makeUploadRequest({
- url: server.url,
- path: path + '/me/avatar/pick',
- fields,
- attaches,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct params', async function () {
- const fields = {}
- const attaches = {
- avatarfile: buildAbsoluteFixturePath('avatar.png')
- }
- await makeUploadRequest({
- url: server.url,
- path: path + '/me/avatar/pick',
- token: server.accessToken,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When managing my scoped tokens', function () {
-
- it('Should fail to get my scoped tokens with an non authenticated user', async function () {
- await server.users.getMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail to get my scoped tokens with a bad token', async function () {
- await server.users.getMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
-
- })
-
- it('Should succeed to get my scoped tokens', async function () {
- await server.users.getMyScopedTokens()
- })
-
- it('Should fail to renew my scoped tokens with an non authenticated user', async function () {
- await server.users.renewMyScopedTokens({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail to renew my scoped tokens with a bad token', async function () {
- await server.users.renewMyScopedTokens({ token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should succeed to renew my scoped tokens', async function () {
- await server.users.renewMyScopedTokens()
- })
- })
-
- describe('When getting my information', function () {
- it('Should fail with a non authenticated user', async function () {
- await server.users.getMyInfo({ token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should success with the correct parameters', async function () {
- await server.users.getMyInfo({ token: userToken })
- })
- })
-
- describe('When getting my video rating', function () {
- let command: UsersCommand
-
- before(function () {
- command = server.users
- })
-
- it('Should fail with a non authenticated user', async function () {
- await command.getMyRating({ token: 'fake_token', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with an incorrect video uuid', async function () {
- await command.getMyRating({ videoId: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown video', async function () {
- await command.getMyRating({ videoId: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await command.getMyRating({ videoId: video.id })
- await command.getMyRating({ videoId: video.uuid })
- await command.getMyRating({ videoId: video.shortUUID })
- })
- })
-
- describe('When retrieving my global ratings', function () {
- const path = '/api/v1/accounts/user1/ratings'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, userToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, userToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, userToken)
- })
-
- it('Should fail with a unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a another user', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad type', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userToken,
- query: { rating: 'toto ' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When getting my global followers', function () {
- const path = '/api/v1/accounts/user1/followers'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, userToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, userToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, userToken)
- })
-
- it('Should fail with a unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a another user', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When blocking/unblocking/removing user', function () {
-
- it('Should fail with an incorrect id', async function () {
- const options = { userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
-
- await server.users.remove(options)
- await server.users.banUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.users.unbanUser({ userId: 'blabla' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with the root user', async function () {
- const options = { userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
-
- await server.users.remove(options)
- await server.users.banUser(options)
- await server.users.unbanUser(options)
- })
-
- it('Should return 404 with a non existing id', async function () {
- const options = { userId: 4545454, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await server.users.remove(options)
- await server.users.banUser(options)
- await server.users.unbanUser(options)
- })
-
- it('Should fail with a non admin user', async function () {
- const options = { userId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
-
- await server.users.remove(options)
- await server.users.banUser(options)
- await server.users.unbanUser(options)
- })
-
- it('Should fail on a moderator with a moderator', async function () {
- const options = { userId: moderatorId, token: moderatorToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
-
- await server.users.remove(options)
- await server.users.banUser(options)
- await server.users.unbanUser(options)
- })
-
- it('Should succeed on a user with a moderator', async function () {
- const options = { userId, token: moderatorToken }
-
- await server.users.banUser(options)
- await server.users.unbanUser(options)
- })
- })
-
- describe('When deleting our account', function () {
-
- it('Should fail with with the root account', async function () {
- await server.users.deleteMe({ expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/plugins.ts b/server/tests/api/check-params/plugins.ts
deleted file mode 100644
index e08cd7ab8..000000000
--- a/server/tests/api/check-params/plugins.ts
+++ /dev/null
@@ -1,490 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode, PeerTubePlugin, PluginType } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test server plugins API validators', function () {
- let server: PeerTubeServer
- let userAccessToken = null
-
- const npmPlugin = 'peertube-plugin-hello-world'
- const pluginName = 'hello-world'
- let npmVersion: string
-
- const themePlugin = 'peertube-theme-background-red'
- const themeName = 'background-red'
- let themeVersion: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(60000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'password'
- }
-
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
-
- {
- const res = await server.plugins.install({ npmName: npmPlugin })
- const plugin = res.body as PeerTubePlugin
- npmVersion = plugin.version
- }
-
- {
- const res = await server.plugins.install({ npmName: themePlugin })
- const plugin = res.body as PeerTubePlugin
- themeVersion = plugin.version
- }
- })
-
- describe('With static plugin routes', function () {
- it('Should fail with an unknown plugin name/plugin version', async function () {
- const paths = [
- '/plugins/' + pluginName + '/0.0.1/auth/fake-auth',
- '/plugins/' + pluginName + '/0.0.1/static/images/chocobo.png',
- '/plugins/' + pluginName + '/0.0.1/client-scripts/client/common-client-plugin.js',
- '/themes/' + themeName + '/0.0.1/static/images/chocobo.png',
- '/themes/' + themeName + '/0.0.1/client-scripts/client/video-watch-client-plugin.js',
- '/themes/' + themeName + '/0.0.1/css/assets/style1.css'
- ]
-
- for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
-
- it('Should fail when requesting a plugin in the theme path', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/themes/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with invalid versions', async function () {
- const paths = [
- '/plugins/' + pluginName + '/0.0.1.1/auth/fake-auth',
- '/plugins/' + pluginName + '/0.0.1.1/static/images/chocobo.png',
- '/plugins/' + pluginName + '/0.1/client-scripts/client/common-client-plugin.js',
- '/themes/' + themeName + '/1/static/images/chocobo.png',
- '/themes/' + themeName + '/0.0.1000a/client-scripts/client/video-watch-client-plugin.js',
- '/themes/' + themeName + '/0.a.1/css/assets/style1.css'
- ]
-
- for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
- })
-
- it('Should fail with invalid paths', async function () {
- const paths = [
- '/plugins/' + pluginName + '/' + npmVersion + '/static/images/../chocobo.png',
- '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/../client/common-client-plugin.js',
- '/themes/' + themeName + '/' + themeVersion + '/static/../images/chocobo.png',
- '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/video-watch-client-plugin.js/..',
- '/themes/' + themeName + '/' + themeVersion + '/css/../assets/style1.css'
- ]
-
- for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
- })
-
- it('Should fail with an unknown auth name', async function () {
- const path = '/plugins/' + pluginName + '/' + npmVersion + '/auth/bad-auth'
-
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an unknown static file', async function () {
- const paths = [
- '/plugins/' + pluginName + '/' + npmVersion + '/static/fake/chocobo.png',
- '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/client/fake.js',
- '/themes/' + themeName + '/' + themeVersion + '/static/fake/chocobo.png',
- '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/fake.js'
- ]
-
- for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
-
- it('Should fail with an unknown CSS file', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/themes/' + themeName + '/' + themeVersion + '/css/assets/fake.css',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- const paths = [
- '/plugins/' + pluginName + '/' + npmVersion + '/static/images/chocobo.png',
- '/plugins/' + pluginName + '/' + npmVersion + '/client-scripts/client/common-client-plugin.js',
- '/themes/' + themeName + '/' + themeVersion + '/static/images/chocobo.png',
- '/themes/' + themeName + '/' + themeVersion + '/client-scripts/client/video-watch-client-plugin.js',
- '/themes/' + themeName + '/' + themeVersion + '/css/assets/style1.css'
- ]
-
- for (const p of paths) {
- await makeGetRequest({ url: server.url, path: p, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const authPath = '/plugins/' + pluginName + '/' + npmVersion + '/auth/fake-auth'
- await makeGetRequest({ url: server.url, path: authPath, expectedStatus: HttpStatusCode.FOUND_302 })
- })
- })
-
- describe('When listing available plugins/themes', function () {
- const path = '/api/v1/plugins/available'
- const baseQuery = {
- search: 'super search',
- pluginType: PluginType.PLUGIN,
- currentPeerTubeEngine: '1.2.3'
- }
-
- it('Should fail with an invalid token', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: 'fake_token',
- query: baseQuery,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- query: baseQuery,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an invalid plugin type', async function () {
- const query = { ...baseQuery, pluginType: 5 }
-
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query
- })
- })
-
- it('Should fail with an invalid current peertube engine', async function () {
- const query = { ...baseQuery, currentPeerTubeEngine: '1.0' }
-
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: baseQuery,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When listing local plugins/themes', function () {
- const path = '/api/v1/plugins'
- const baseQuery = {
- pluginType: PluginType.THEME
- }
-
- it('Should fail with an invalid token', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: 'fake_token',
- query: baseQuery,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- query: baseQuery,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an invalid plugin type', async function () {
- const query = { ...baseQuery, pluginType: 5 }
-
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: baseQuery,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When getting a plugin or the registered settings or public settings', function () {
- const path = '/api/v1/plugins/'
-
- it('Should fail with an invalid token', async function () {
- for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- }
- })
-
- it('Should fail if the user is not an administrator', async function () {
- for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
- })
-
- it('Should fail with an invalid npm name', async function () {
- for (const suffix of [ 'toto', 'toto/registered-settings', 'toto/public-settings' ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
-
- for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings', 'peertube-plugin-TOTO/public-settings' ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
- })
-
- it('Should fail with an unknown plugin', async function () {
- for (const suffix of [ 'peertube-plugin-toto', 'peertube-plugin-toto/registered-settings', 'peertube-plugin-toto/public-settings' ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- }
- })
-
- it('Should succeed with the correct parameters', async function () {
- for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings`, `${npmPlugin}/public-settings` ]) {
- await makeGetRequest({
- url: server.url,
- path: path + suffix,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- })
- })
-
- describe('When updating plugin settings', function () {
- const path = '/api/v1/plugins/'
- const settings = { setting1: 'value1' }
-
- it('Should fail with an invalid token', async function () {
- await makePutBodyRequest({
- url: server.url,
- path: path + npmPlugin + '/settings',
- fields: { settings },
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePutBodyRequest({
- url: server.url,
- path: path + npmPlugin + '/settings',
- fields: { settings },
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid npm name', async function () {
- await makePutBodyRequest({
- url: server.url,
- path: path + 'toto/settings',
- fields: { settings },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makePutBodyRequest({
- url: server.url,
- path: path + 'peertube-plugin-TOTO/settings',
- fields: { settings },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown plugin', async function () {
- await makePutBodyRequest({
- url: server.url,
- path: path + 'peertube-plugin-toto/settings',
- fields: { settings },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePutBodyRequest({
- url: server.url,
- path: path + npmPlugin + '/settings',
- fields: { settings },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When installing/updating/uninstalling a plugin', function () {
- const path = '/api/v1/plugins/'
-
- it('Should fail with an invalid token', async function () {
- for (const suffix of [ 'install', 'update', 'uninstall' ]) {
- await makePostBodyRequest({
- url: server.url,
- path: path + suffix,
- fields: { npmName: npmPlugin },
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- }
- })
-
- it('Should fail if the user is not an administrator', async function () {
- for (const suffix of [ 'install', 'update', 'uninstall' ]) {
- await makePostBodyRequest({
- url: server.url,
- path: path + suffix,
- fields: { npmName: npmPlugin },
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
- })
-
- it('Should fail with an invalid npm name', async function () {
- for (const suffix of [ 'install', 'update', 'uninstall' ]) {
- await makePostBodyRequest({
- url: server.url,
- path: path + suffix,
- fields: { npmName: 'toto' },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
-
- for (const suffix of [ 'install', 'update', 'uninstall' ]) {
- await makePostBodyRequest({
- url: server.url,
- path: path + suffix,
- fields: { npmName: 'peertube-plugin-TOTO' },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
- })
-
- it('Should succeed with the correct parameters', async function () {
- const it = [
- { suffix: 'install', status: HttpStatusCode.OK_200 },
- { suffix: 'update', status: HttpStatusCode.OK_200 },
- { suffix: 'uninstall', status: HttpStatusCode.NO_CONTENT_204 }
- ]
-
- for (const obj of it) {
- await makePostBodyRequest({
- url: server.url,
- path: path + obj.suffix,
- fields: { npmName: npmPlugin },
- token: server.accessToken,
- expectedStatus: obj.status
- })
- }
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/redundancy.ts b/server/tests/api/check-params/redundancy.ts
deleted file mode 100644
index 73dfd489d..000000000
--- a/server/tests/api/check-params/redundancy.ts
+++ /dev/null
@@ -1,240 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode, VideoCreateResult } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test server redundancy API validators', function () {
- let servers: PeerTubeServer[]
- let userAccessToken = null
- let videoIdLocal: number
- let videoRemote: VideoCreateResult
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(160000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await doubleFollow(servers[0], servers[1])
-
- const user = {
- username: 'user1',
- password: 'password'
- }
-
- await servers[0].users.create({ username: user.username, password: user.password })
- userAccessToken = await servers[0].login.getAccessToken(user)
-
- videoIdLocal = (await servers[0].videos.quickUpload({ name: 'video' })).id
-
- const remoteUUID = (await servers[1].videos.quickUpload({ name: 'video' })).uuid
-
- await waitJobs(servers)
-
- videoRemote = await servers[0].videos.get({ id: remoteUUID })
- })
-
- describe('When listing redundancies', function () {
- const path = '/api/v1/server/redundancy/videos'
-
- let url: string
- let token: string
-
- before(function () {
- url = servers[0].url
- token = servers[0].accessToken
- })
-
- it('Should fail with an invalid token', async function () {
- await makeGetRequest({ url, path, token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeGetRequest({ url, path, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(url, path, servers[0].accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(url, path, servers[0].accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(url, path, servers[0].accessToken)
- })
-
- it('Should fail with a bad target', async function () {
- await makeGetRequest({ url, path, token, query: { target: 'bad target' } })
- })
-
- it('Should fail without target', async function () {
- await makeGetRequest({ url, path, token })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url, path, token, query: { target: 'my-videos' }, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When manually adding a redundancy', function () {
- const path = '/api/v1/server/redundancy/videos'
-
- let url: string
- let token: string
-
- before(function () {
- url = servers[0].url
- token = servers[0].accessToken
- })
-
- it('Should fail with an invalid token', async function () {
- await makePostBodyRequest({ url, path, token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePostBodyRequest({ url, path, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail without a video id', async function () {
- await makePostBodyRequest({ url, path, token })
- })
-
- it('Should fail with an incorrect video id', async function () {
- await makePostBodyRequest({ url, path, token, fields: { videoId: 'peertube' } })
- })
-
- it('Should fail with a not found video id', async function () {
- await makePostBodyRequest({ url, path, token, fields: { videoId: 6565 }, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a local a video id', async function () {
- await makePostBodyRequest({ url, path, token, fields: { videoId: videoIdLocal } })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url,
- path,
- token,
- fields: { videoId: videoRemote.shortUUID },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should fail if the video is already duplicated', async function () {
- this.timeout(30000)
-
- await waitJobs(servers)
-
- await makePostBodyRequest({
- url,
- path,
- token,
- fields: { videoId: videoRemote.uuid },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
- })
-
- describe('When manually removing a redundancy', function () {
- const path = '/api/v1/server/redundancy/videos/'
-
- let url: string
- let token: string
-
- before(function () {
- url = servers[0].url
- token = servers[0].accessToken
- })
-
- it('Should fail with an invalid token', async function () {
- await makeDeleteRequest({ url, path: path + '1', token: 'fake_token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makeDeleteRequest({ url, path: path + '1', token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with an incorrect video id', async function () {
- await makeDeleteRequest({ url, path: path + 'toto', token })
- })
-
- it('Should fail with a not found video redundancy', async function () {
- await makeDeleteRequest({ url, path: path + '454545', token, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('When updating server redundancy', function () {
- const path = '/api/v1/server/redundancy'
-
- it('Should fail with an invalid token', async function () {
- await makePutBodyRequest({
- url: servers[0].url,
- path: path + '/' + servers[1].host,
- fields: { redundancyAllowed: true },
- token: 'fake_token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if the user is not an administrator', async function () {
- await makePutBodyRequest({
- url: servers[0].url,
- path: path + '/' + servers[1].host,
- fields: { redundancyAllowed: true },
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail if we do not follow this server', async function () {
- await makePutBodyRequest({
- url: servers[0].url,
- path: path + '/example.com',
- fields: { redundancyAllowed: true },
- token: servers[0].accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail without de redundancyAllowed param', async function () {
- await makePutBodyRequest({
- url: servers[0].url,
- path: path + '/' + servers[1].host,
- fields: { blabla: true },
- token: servers[0].accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePutBodyRequest({
- url: servers[0].url,
- path: path + '/' + servers[1].host,
- fields: { redundancyAllowed: true },
- token: servers[0].accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/registrations.ts b/server/tests/api/check-params/registrations.ts
deleted file mode 100644
index 8cbecdd07..000000000
--- a/server/tests/api/check-params/registrations.ts
+++ /dev/null
@@ -1,446 +0,0 @@
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { omit } from '@shared/core-utils'
-import { HttpStatusCode, UserRole } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar
-} from '@shared/server-commands'
-
-describe('Test registrations API validators', function () {
- let server: PeerTubeServer
- let userToken: string
- let moderatorToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultAccountAvatar([ server ])
- await setDefaultChannelAvatar([ server ])
-
- await server.config.enableSignup(false);
-
- ({ token: moderatorToken } = await server.users.generate('moderator', UserRole.MODERATOR));
- ({ token: userToken } = await server.users.generate('user', UserRole.USER))
- })
-
- describe('Register', function () {
- const registrationPath = '/api/v1/users/register'
- const registrationRequestPath = '/api/v1/users/registrations/request'
-
- const baseCorrectParams = {
- username: 'user3',
- displayName: 'super user',
- email: 'test3@example.com',
- password: 'my super password',
- registrationReason: 'my super registration reason'
- }
-
- describe('When registering a new user or requesting user registration', function () {
-
- async function check (fields: any, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
- await server.config.enableSignup(false)
- await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus })
-
- await server.config.enableSignup(true)
- await makePostBodyRequest({ url: server.url, path: registrationRequestPath, fields, expectedStatus })
- }
-
- it('Should fail with a too small username', async function () {
- const fields = { ...baseCorrectParams, username: '' }
-
- await check(fields)
- })
-
- it('Should fail with a too long username', async function () {
- const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
-
- await check(fields)
- })
-
- it('Should fail with an incorrect username', async function () {
- const fields = { ...baseCorrectParams, username: 'my username' }
-
- await check(fields)
- })
-
- it('Should fail with a missing email', async function () {
- const fields = omit(baseCorrectParams, [ 'email' ])
-
- await check(fields)
- })
-
- it('Should fail with an invalid email', async function () {
- const fields = { ...baseCorrectParams, email: 'test_example.com' }
-
- await check(fields)
- })
-
- it('Should fail with a too small password', async function () {
- const fields = { ...baseCorrectParams, password: 'bla' }
-
- await check(fields)
- })
-
- it('Should fail with a too long password', async function () {
- const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
-
- await check(fields)
- })
-
- it('Should fail if we register a user with the same username', async function () {
- const fields = { ...baseCorrectParams, username: 'root' }
-
- await check(fields, HttpStatusCode.CONFLICT_409)
- })
-
- it('Should fail with a "peertube" username', async function () {
- const fields = { ...baseCorrectParams, username: 'peertube' }
-
- await check(fields, HttpStatusCode.CONFLICT_409)
- })
-
- it('Should fail if we register a user with the same email', async function () {
- const fields = { ...baseCorrectParams, email: 'admin' + server.internalServerNumber + '@example.com' }
-
- await check(fields, HttpStatusCode.CONFLICT_409)
- })
-
- it('Should fail with a bad display name', async function () {
- const fields = { ...baseCorrectParams, displayName: 'a'.repeat(150) }
-
- await check(fields)
- })
-
- it('Should fail with a bad channel name', async function () {
- const fields = { ...baseCorrectParams, channel: { name: '[]azf', displayName: 'toto' } }
-
- await check(fields)
- })
-
- it('Should fail with a bad channel display name', async function () {
- const fields = { ...baseCorrectParams, channel: { name: 'toto', displayName: '' } }
-
- await check(fields)
- })
-
- it('Should fail with a channel name that is the same as username', async function () {
- const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
- const fields = { ...baseCorrectParams, ...source }
-
- await check(fields)
- })
-
- it('Should fail with an existing channel', async function () {
- const attributes = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
- await server.channels.create({ attributes })
-
- const fields = { ...baseCorrectParams, channel: { name: 'existing_channel', displayName: 'toto' } }
-
- await check(fields, HttpStatusCode.CONFLICT_409)
- })
-
- it('Should fail on a server with registration disabled', async function () {
- this.timeout(60000)
-
- await server.config.updateExistingSubConfig({
- newConfig: {
- signup: {
- enabled: false
- }
- }
- })
-
- await server.registrations.register({ username: 'user4', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await server.registrations.requestRegistration({
- username: 'user4',
- registrationReason: 'reason',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail if the user limit is reached', async function () {
- this.timeout(60000)
-
- const { total } = await server.users.list()
-
- await server.config.enableSignup(false, total)
- await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
-
- await server.config.enableSignup(true, total)
- await server.registrations.requestRegistration({
- username: 'user42',
- registrationReason: 'reason',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed if the user limit is not reached', async function () {
- this.timeout(60000)
-
- const { total } = await server.users.list()
-
- await server.config.enableSignup(false, total + 1)
- await server.registrations.register({ username: 'user43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
-
- await server.config.enableSignup(true, total + 2)
- await server.registrations.requestRegistration({
- username: 'user44',
- registrationReason: 'reason',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('On direct registration', function () {
-
- it('Should succeed with the correct params', async function () {
- await server.config.enableSignup(false)
-
- const fields = {
- username: 'user_direct_1',
- displayName: 'super user direct 1',
- email: 'user_direct_1@example.com',
- password: 'my super password',
- channel: { name: 'super_user_direct_1_channel', displayName: 'super user direct 1 channel' }
- }
-
- await makePostBodyRequest({ url: server.url, path: registrationPath, fields, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- })
-
- it('Should fail if the instance requires approval', async function () {
- this.timeout(60000)
-
- await server.config.enableSignup(true)
- await server.registrations.register({ username: 'user42', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
- })
-
- describe('On registration request', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await server.config.enableSignup(true)
- })
-
- it('Should fail with an invalid registration reason', async function () {
- for (const registrationReason of [ '', 't', 't'.repeat(5000) ]) {
- await server.registrations.requestRegistration({
- username: 'user_request_1',
- registrationReason,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
- })
-
- it('Should succeed with the correct params', async function () {
- await server.registrations.requestRegistration({
- username: 'user_request_2',
- registrationReason: 'tt',
- channel: {
- displayName: 'my user request 2 channel',
- name: 'user_request_2_channel'
- }
- })
- })
-
- it('Should fail if the username is already awaiting registration approval', async function () {
- await server.registrations.requestRegistration({
- username: 'user_request_2',
- registrationReason: 'tt',
- channel: {
- displayName: 'my user request 42 channel',
- name: 'user_request_42_channel'
- },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail if the email is already awaiting registration approval', async function () {
- await server.registrations.requestRegistration({
- username: 'user42',
- email: 'user_request_2@example.com',
- registrationReason: 'tt',
- channel: {
- displayName: 'my user request 42 channel',
- name: 'user_request_42_channel'
- },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail if the channel is already awaiting registration approval', async function () {
- await server.registrations.requestRegistration({
- username: 'user42',
- registrationReason: 'tt',
- channel: {
- displayName: 'my user request 2 channel',
- name: 'user_request_2_channel'
- },
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail if the instance does not require approval', async function () {
- this.timeout(60000)
-
- await server.config.enableSignup(false)
-
- await server.registrations.requestRegistration({
- username: 'user42',
- registrationReason: 'toto',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
- })
-
- describe('Registrations accept/reject', function () {
- let id1: number
- let id2: number
-
- before(async function () {
- this.timeout(60000)
-
- await server.config.enableSignup(true);
-
- ({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_2', registrationReason: 'toto' }));
- ({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_3', registrationReason: 'toto' }))
- })
-
- it('Should fail to accept/reject registration without token', async function () {
- const options = { id: id1, moderationResponse: 'tt', token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- })
-
- it('Should fail to accept/reject registration with a non moderator user', async function () {
- const options = { id: id1, moderationResponse: 'tt', token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- })
-
- it('Should fail to accept/reject registration with a bad registration id', async function () {
- {
- const options = { id: 't' as any, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- }
-
- {
- const options = { id: 42, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- }
- })
-
- it('Should fail to accept/reject registration with a bad moderation resposne', async function () {
- for (const moderationResponse of [ '', 't', 't'.repeat(5000) ]) {
- const options = { id: id1, moderationResponse, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- }
- })
-
- it('Should succeed to accept a registration', async function () {
- await server.registrations.accept({ id: id1, moderationResponse: 'tt', token: moderatorToken })
- })
-
- it('Should succeed to reject a registration', async function () {
- await server.registrations.reject({ id: id2, moderationResponse: 'tt', token: moderatorToken })
- })
-
- it('Should fail to accept/reject a registration that was already accepted/rejected', async function () {
- for (const id of [ id1, id2 ]) {
- const options = { id, moderationResponse: 'tt', token: moderatorToken, expectedStatus: HttpStatusCode.CONFLICT_409 }
- await server.registrations.accept(options)
- await server.registrations.reject(options)
- }
- })
- })
-
- describe('Registrations deletion', function () {
- let id1: number
- let id2: number
- let id3: number
-
- before(async function () {
- ({ id: id1 } = await server.registrations.requestRegistration({ username: 'request_4', registrationReason: 'toto' }));
- ({ id: id2 } = await server.registrations.requestRegistration({ username: 'request_5', registrationReason: 'toto' }));
- ({ id: id3 } = await server.registrations.requestRegistration({ username: 'request_6', registrationReason: 'toto' }))
-
- await server.registrations.accept({ id: id2, moderationResponse: 'tt' })
- await server.registrations.reject({ id: id3, moderationResponse: 'tt' })
- })
-
- it('Should fail to delete registration without token', async function () {
- await server.registrations.delete({ id: id1, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail to delete registration with a non moderator user', async function () {
- await server.registrations.delete({ id: id1, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail to delete registration with a bad registration id', async function () {
- await server.registrations.delete({ id: 't' as any, token: moderatorToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.registrations.delete({ id: 42, token: moderatorToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.registrations.delete({ id: id1, token: moderatorToken })
- await server.registrations.delete({ id: id2, token: moderatorToken })
- await server.registrations.delete({ id: id3, token: moderatorToken })
- })
- })
-
- describe('Listing registrations', function () {
- const path = '/api/v1/users/registrations'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await server.registrations.list({
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await server.registrations.list({
- token: userToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.registrations.list({
- token: moderatorToken,
- search: 'toto'
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/runners.ts b/server/tests/api/check-params/runners.ts
deleted file mode 100644
index 0e5012da5..000000000
--- a/server/tests/api/check-params/runners.ts
+++ /dev/null
@@ -1,910 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { basename } from 'path'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import {
- HttpStatusCode,
- isVideoStudioTaskIntro,
- RunnerJob,
- RunnerJobState,
- RunnerJobStudioTranscodingPayload,
- RunnerJobSuccessPayload,
- RunnerJobUpdatePayload,
- VideoPrivacy,
- VideoStudioTaskIntro
-} from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makePostBodyRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- VideoStudioCommand,
- waitJobs
-} from '@shared/server-commands'
-
-const badUUID = '910ec12a-d9e6-458b-a274-0abb655f9464'
-
-describe('Test managing runners', function () {
- let server: PeerTubeServer
-
- let userToken: string
-
- let registrationTokenId: number
- let registrationToken: string
-
- let runnerToken: string
- let runnerToken2: string
-
- let completedJobToken: string
- let completedJobUUID: string
-
- let cancelledJobToken: string
- let cancelledJobUUID: string
-
- before(async function () {
- this.timeout(120000)
-
- const config = {
- rates_limit: {
- api: {
- max: 5000
- }
- }
- }
-
- server = await createSingleServer(1, config)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- userToken = await server.users.generateUserAndToken('user1')
-
- const { data } = await server.runnerRegistrationTokens.list()
- registrationToken = data[0].registrationToken
- registrationTokenId = data[0].id
-
- await server.config.enableTranscoding({ hls: true, webVideo: true })
- await server.config.enableStudio()
- await server.config.enableRemoteTranscoding()
- await server.config.enableRemoteStudio()
-
- runnerToken = await server.runners.autoRegisterRunner()
- runnerToken2 = await server.runners.autoRegisterRunner()
-
- {
- await server.videos.quickUpload({ name: 'video 1' })
- await server.videos.quickUpload({ name: 'video 2' })
-
- await waitJobs([ server ])
-
- {
- const job = await server.runnerJobs.autoProcessWebVideoJob(runnerToken)
- completedJobToken = job.jobToken
- completedJobUUID = job.uuid
- }
-
- {
- const { job } = await server.runnerJobs.autoAccept({ runnerToken })
- cancelledJobToken = job.jobToken
- cancelledJobUUID = job.uuid
- await server.runnerJobs.cancelByAdmin({ jobUUID: cancelledJobUUID })
- }
- }
- })
-
- describe('Managing runner registration tokens', function () {
-
- describe('Common', function () {
-
- it('Should fail to generate, list or delete runner registration token without oauth token', async function () {
- const expectedStatus = HttpStatusCode.UNAUTHORIZED_401
-
- await server.runnerRegistrationTokens.generate({ token: null, expectedStatus })
- await server.runnerRegistrationTokens.list({ token: null, expectedStatus })
- await server.runnerRegistrationTokens.delete({ token: null, id: registrationTokenId, expectedStatus })
- })
-
- it('Should fail to generate, list or delete runner registration token without admin rights', async function () {
- const expectedStatus = HttpStatusCode.FORBIDDEN_403
-
- await server.runnerRegistrationTokens.generate({ token: userToken, expectedStatus })
- await server.runnerRegistrationTokens.list({ token: userToken, expectedStatus })
- await server.runnerRegistrationTokens.delete({ token: userToken, id: registrationTokenId, expectedStatus })
- })
- })
-
- describe('Delete', function () {
-
- it('Should fail to delete with a bad id', async function () {
- await server.runnerRegistrationTokens.delete({ id: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('List', function () {
- const path = '/api/v1/runners/registration-tokens'
-
- it('Should fail to list with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should succeed to list with the correct params', async function () {
- await server.runnerRegistrationTokens.list({ start: 0, count: 5, sort: '-createdAt' })
- })
- })
- })
-
- describe('Managing runners', function () {
- let toDeleteId: number
-
- describe('Register', function () {
- const name = 'runner name'
-
- it('Should fail with a bad registration token', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await server.runners.register({ name, registrationToken: 'a'.repeat(4000), expectedStatus })
- await server.runners.register({ name, registrationToken: null, expectedStatus })
- })
-
- it('Should fail with an unknown registration token', async function () {
- await server.runners.register({ name, registrationToken: 'aaa', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a bad name', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await server.runners.register({ name: '', registrationToken, expectedStatus })
- await server.runners.register({ name: 'a'.repeat(200), registrationToken, expectedStatus })
- })
-
- it('Should fail with an invalid description', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await server.runners.register({ name, description: '', registrationToken, expectedStatus })
- await server.runners.register({ name, description: 'a'.repeat(5000), registrationToken, expectedStatus })
- })
-
- it('Should succeed with the correct params', async function () {
- const { id } = await server.runners.register({ name, description: 'super description', registrationToken })
-
- toDeleteId = id
- })
-
- it('Should fail with the same runner name', async function () {
- await server.runners.register({
- name,
- description: 'super description',
- registrationToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('Delete', function () {
-
- it('Should fail without oauth token', async function () {
- await server.runners.delete({ token: null, id: toDeleteId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without admin rights', async function () {
- await server.runners.delete({ token: userToken, id: toDeleteId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad id', async function () {
- await server.runners.delete({ id: 'hi' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown id', async function () {
- await server.runners.delete({ id: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.runners.delete({ id: toDeleteId })
- })
- })
-
- describe('List', function () {
- const path = '/api/v1/runners'
-
- it('Should fail without oauth token', async function () {
- await server.runners.list({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without admin rights', async function () {
- await server.runners.list({ token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail to list with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an invalid state', async function () {
- await server.runners.list({ start: 0, count: 5, sort: '-createdAt' })
- })
-
- it('Should succeed to list with the correct params', async function () {
- await server.runners.list({ start: 0, count: 5, sort: '-createdAt' })
- })
- })
-
- })
-
- describe('Runner jobs by admin', function () {
-
- describe('Cancel', function () {
- let jobUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- jobUUID = availableJobs[0].uuid
- })
-
- it('Should fail without oauth token', async function () {
- await server.runnerJobs.cancelByAdmin({ token: null, jobUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without admin rights', async function () {
- await server.runnerJobs.cancelByAdmin({ token: userToken, jobUUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad job uuid', async function () {
- await server.runnerJobs.cancelByAdmin({ jobUUID: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown job uuid', async function () {
- const jobUUID = badUUID
- await server.runnerJobs.cancelByAdmin({ jobUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an already cancelled job', async function () {
- await server.runnerJobs.cancelByAdmin({ jobUUID: cancelledJobUUID, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.runnerJobs.cancelByAdmin({ jobUUID })
- })
- })
-
- describe('List', function () {
- const path = '/api/v1/runners/jobs'
-
- it('Should fail without oauth token', async function () {
- await server.runnerJobs.list({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without admin rights', async function () {
- await server.runnerJobs.list({ token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail to list with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail to list with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an invalid state', async function () {
- await server.runnerJobs.list({ start: 0, count: 5, sort: '-createdAt', stateOneOf: 42 as any })
- await server.runnerJobs.list({ start: 0, count: 5, sort: '-createdAt', stateOneOf: [ 42 ] as any })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.runnerJobs.list({ start: 0, count: 5, sort: '-createdAt', stateOneOf: [ RunnerJobState.COMPLETED ] })
- })
- })
-
- describe('Delete', function () {
- let jobUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- jobUUID = availableJobs[0].uuid
- })
-
- it('Should fail without oauth token', async function () {
- await server.runnerJobs.deleteByAdmin({ token: null, jobUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail without admin rights', async function () {
- await server.runnerJobs.deleteByAdmin({ token: userToken, jobUUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad job uuid', async function () {
- await server.runnerJobs.deleteByAdmin({ jobUUID: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown job uuid', async function () {
- const jobUUID = badUUID
- await server.runnerJobs.deleteByAdmin({ jobUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await server.runnerJobs.deleteByAdmin({ jobUUID })
- })
- })
-
- })
-
- describe('Runner jobs by runners', function () {
- let jobUUID: string
- let jobToken: string
- let videoUUID: string
-
- let jobUUID2: string
- let jobToken2: string
-
- let videoUUID2: string
-
- let pendingUUID: string
-
- let videoStudioUUID: string
- let studioFile: string
-
- let liveAcceptedJob: RunnerJob & { jobToken: string }
- let studioAcceptedJob: RunnerJob & { jobToken: string }
-
- async function fetchVideoInputFiles (options: {
- jobUUID: string
- videoUUID: string
- runnerToken: string
- jobToken: string
- expectedStatus: HttpStatusCode
- }) {
- const { jobUUID, expectedStatus, videoUUID, runnerToken, jobToken } = options
-
- const basePath = '/api/v1/runners/jobs/' + jobUUID + '/files/videos/' + videoUUID
- const paths = [ `${basePath}/max-quality`, `${basePath}/previews/max-quality` ]
-
- for (const path of paths) {
- await makePostBodyRequest({ url: server.url, path, fields: { runnerToken, jobToken }, expectedStatus })
- }
- }
-
- async function fetchStudioFiles (options: {
- jobUUID: string
- videoUUID: string
- runnerToken: string
- jobToken: string
- studioFile?: string
- expectedStatus: HttpStatusCode
- }) {
- const { jobUUID, expectedStatus, videoUUID, runnerToken, jobToken, studioFile } = options
-
- const path = `/api/v1/runners/jobs/${jobUUID}/files/videos/${videoUUID}/studio/task-files/${studioFile}`
-
- await makePostBodyRequest({ url: server.url, path, fields: { runnerToken, jobToken }, expectedStatus })
- }
-
- before(async function () {
- this.timeout(120000)
-
- {
- await server.runnerJobs.cancelAllJobs({ state: RunnerJobState.PENDING })
- }
-
- {
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoUUID = uuid
-
- await waitJobs([ server ])
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken })
- jobUUID = job.uuid
- jobToken = job.jobToken
- }
-
- {
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoUUID2 = uuid
-
- await waitJobs([ server ])
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken: runnerToken2 })
- jobUUID2 = job.uuid
- jobToken2 = job.jobToken
- }
-
- {
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- pendingUUID = availableJobs[0].uuid
- }
-
- {
- await server.config.disableTranscoding()
-
- const { uuid } = await server.videos.quickUpload({ name: 'video studio' })
- videoStudioUUID = uuid
-
- await server.config.enableTranscoding({ hls: true, webVideo: true })
- await server.config.enableStudio()
-
- await server.videoStudio.createEditionTasks({
- videoId: videoStudioUUID,
- tasks: VideoStudioCommand.getComplexTask()
- })
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'video-studio-transcoding' })
- studioAcceptedJob = job
-
- const tasks = (job.payload as RunnerJobStudioTranscodingPayload).tasks
- const fileUrl = (tasks.find(t => isVideoStudioTaskIntro(t)) as VideoStudioTaskIntro).options.file as string
- studioFile = basename(fileUrl)
- }
-
- {
- await server.config.enableLive({
- allowReplay: false,
- resolutions: 'max',
- transcoding: true
- })
-
- const { live } = await server.live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await waitJobs([ server ])
-
- await server.runnerJobs.requestLiveJob(runnerToken)
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'live-rtmp-hls-transcoding' })
- liveAcceptedJob = job
-
- await stopFfmpeg(ffmpegCommand)
- }
- })
-
- describe('Common runner tokens validations', function () {
-
- async function testEndpoints (options: {
- jobUUID: string
- runnerToken: string
- jobToken: string
- expectedStatus: HttpStatusCode
- }) {
- await server.runnerJobs.abort({ ...options, reason: 'reason' })
- await server.runnerJobs.update({ ...options })
- await server.runnerJobs.error({ ...options, message: 'message' })
- await server.runnerJobs.success({ ...options, payload: { videoFile: 'video_short.mp4' } })
- }
-
- it('Should fail with an invalid job uuid', async function () {
- const options = { jobUUID: 'a', runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
-
- await testEndpoints({ ...options, jobToken })
- await fetchVideoInputFiles({ ...options, videoUUID, jobToken })
- await fetchStudioFiles({ ...options, videoUUID, jobToken: studioAcceptedJob.jobToken, studioFile })
- })
-
- it('Should fail with an unknown job uuid', async function () {
- const options = { jobUUID: badUUID, runnerToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobToken })
- await fetchVideoInputFiles({ ...options, videoUUID, jobToken })
- await fetchStudioFiles({ ...options, jobToken: studioAcceptedJob.jobToken, videoUUID, studioFile })
- })
-
- it('Should fail with an invalid runner token', async function () {
- const options = { runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
-
- await testEndpoints({ ...options, jobUUID, jobToken })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID, jobToken })
- await fetchStudioFiles({
- ...options,
- jobToken: studioAcceptedJob.jobToken,
- jobUUID: studioAcceptedJob.uuid,
- videoUUID: videoStudioUUID,
- studioFile
- })
- })
-
- it('Should fail with an unknown runner token', async function () {
- const options = { runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobUUID, jobToken })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID, jobToken })
- await fetchStudioFiles({
- ...options,
- jobToken: studioAcceptedJob.jobToken,
- jobUUID: studioAcceptedJob.uuid,
- videoUUID: videoStudioUUID,
- studioFile
- })
- })
-
- it('Should fail with an invalid job token job uuid', async function () {
- const options = { runnerToken, jobToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 }
-
- await testEndpoints({ ...options, jobUUID })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID })
- await fetchStudioFiles({ ...options, jobUUID: studioAcceptedJob.uuid, videoUUID: videoStudioUUID, studioFile })
- })
-
- it('Should fail with an unknown job token job uuid', async function () {
- const options = { runnerToken, jobToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobUUID })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID })
- await fetchStudioFiles({ ...options, jobUUID: studioAcceptedJob.uuid, videoUUID: videoStudioUUID, studioFile })
- })
-
- it('Should fail with a runner token not associated to this job', async function () {
- const options = { runnerToken: runnerToken2, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobUUID, jobToken })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID, jobToken })
- await fetchStudioFiles({
- ...options,
- jobToken: studioAcceptedJob.jobToken,
- jobUUID: studioAcceptedJob.uuid,
- videoUUID: videoStudioUUID,
- studioFile
- })
- })
-
- it('Should fail with a job uuid not associated to the job token', async function () {
- {
- const options = { jobUUID: jobUUID2, runnerToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobToken })
- await fetchVideoInputFiles({ ...options, jobToken, videoUUID })
- await fetchStudioFiles({ ...options, jobToken: studioAcceptedJob.jobToken, videoUUID: videoStudioUUID, studioFile })
- }
-
- {
- const options = { runnerToken, jobToken: jobToken2, expectedStatus: HttpStatusCode.NOT_FOUND_404 }
-
- await testEndpoints({ ...options, jobUUID })
- await fetchVideoInputFiles({ ...options, jobUUID, videoUUID })
- await fetchStudioFiles({ ...options, jobUUID: studioAcceptedJob.uuid, videoUUID: videoStudioUUID, studioFile })
- }
- })
- })
-
- describe('Unregister', function () {
-
- it('Should fail without a runner token', async function () {
- await server.runners.unregister({ runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad a runner token', async function () {
- await server.runners.unregister({ runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown runner token', async function () {
- await server.runners.unregister({ runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Request', function () {
-
- it('Should fail without a runner token', async function () {
- await server.runnerJobs.request({ runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad a runner token', async function () {
- await server.runnerJobs.request({ runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown runner token', async function () {
- await server.runnerJobs.request({ runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Accept', function () {
-
- it('Should fail with a bad a job uuid', async function () {
- await server.runnerJobs.accept({ jobUUID: '', runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown job uuid', async function () {
- await server.runnerJobs.accept({ jobUUID: badUUID, runnerToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a job not in pending state', async function () {
- await server.runnerJobs.accept({ jobUUID: completedJobUUID, runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.runnerJobs.accept({ jobUUID: cancelledJobUUID, runnerToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail without a runner token', async function () {
- await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad a runner token', async function () {
- await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown runner token', async function () {
- await server.runnerJobs.accept({ jobUUID: pendingUUID, runnerToken: badUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Abort', function () {
-
- it('Should fail without a reason', async function () {
- await server.runnerJobs.abort({ jobUUID, jobToken, runnerToken, reason: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a bad reason', async function () {
- const reason = 'reason'.repeat(5000)
- await server.runnerJobs.abort({ jobUUID, jobToken, runnerToken, reason, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a job not in processing state', async function () {
- await server.runnerJobs.abort({
- jobUUID: completedJobUUID,
- jobToken: completedJobToken,
- runnerToken,
- reason: 'reason',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('Update', function () {
-
- describe('Common', function () {
-
- it('Should fail with an invalid progress', async function () {
- await server.runnerJobs.update({ jobUUID, jobToken, runnerToken, progress: 101, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a job not in processing state', async function () {
- await server.runnerJobs.update({
- jobUUID: cancelledJobUUID,
- jobToken: cancelledJobToken,
- runnerToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
- })
-
- describe('Live RTMP to HLS', function () {
- const base: RunnerJobUpdatePayload = {
- masterPlaylistFile: 'live/master.m3u8',
- resolutionPlaylistFilename: '0.m3u8',
- resolutionPlaylistFile: 'live/1.m3u8',
- type: 'add-chunk',
- videoChunkFile: 'live/1-000069.ts',
- videoChunkFilename: '1-000068.ts'
- }
-
- function testUpdate (payload: RunnerJobUpdatePayload) {
- return server.runnerJobs.update({
- jobUUID: liveAcceptedJob.uuid,
- jobToken: liveAcceptedJob.jobToken,
- payload,
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
-
- it('Should fail with an invalid resolutionPlaylistFilename', async function () {
- await testUpdate({ ...base, resolutionPlaylistFilename: undefined })
- await testUpdate({ ...base, resolutionPlaylistFilename: 'coucou/hello' })
- await testUpdate({ ...base, resolutionPlaylistFilename: 'hello' })
- })
-
- it('Should fail with an invalid videoChunkFilename', async function () {
- await testUpdate({ ...base, resolutionPlaylistFilename: undefined })
- await testUpdate({ ...base, resolutionPlaylistFilename: 'coucou/hello' })
- await testUpdate({ ...base, resolutionPlaylistFilename: 'hello' })
- })
-
- it('Should fail with an invalid type', async function () {
- await testUpdate({ ...base, type: undefined })
- await testUpdate({ ...base, type: 'toto' as any })
- })
- })
- })
-
- describe('Error', function () {
-
- it('Should fail with a missing error message', async function () {
- await server.runnerJobs.error({ jobUUID, jobToken, runnerToken, message: null, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an invalid error messgae', async function () {
- const message = 'a'.repeat(6000)
- await server.runnerJobs.error({ jobUUID, jobToken, runnerToken, message, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a job not in processing state', async function () {
- await server.runnerJobs.error({
- jobUUID: completedJobUUID,
- jobToken: completedJobToken,
- message: 'my message',
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('Success', function () {
- let vodJobUUID: string
- let vodJobToken: string
-
- describe('Common', function () {
-
- it('Should fail with a job not in processing state', async function () {
- await server.runnerJobs.success({
- jobUUID: completedJobUUID,
- jobToken: completedJobToken,
- payload: { videoFile: 'video_short.mp4' },
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('VOD', function () {
-
- it('Should fail with an invalid vod web video payload', async function () {
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-web-video-transcoding' })
-
- await server.runnerJobs.success({
- jobUUID: job.uuid,
- jobToken: job.jobToken,
- payload: { hello: 'video_short.mp4' } as any,
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- vodJobUUID = job.uuid
- vodJobToken = job.jobToken
- })
-
- it('Should fail with an invalid vod hls payload', async function () {
- // To create HLS jobs
- const payload: RunnerJobSuccessPayload = { videoFile: 'video_short.mp4' }
- await server.runnerJobs.success({ runnerToken, jobUUID: vodJobUUID, jobToken: vodJobToken, payload })
-
- await waitJobs([ server ])
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-hls-transcoding' })
-
- await server.runnerJobs.success({
- jobUUID: job.uuid,
- jobToken: job.jobToken,
- payload: { videoFile: 'video_short.mp4' } as any,
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an invalid vod audio merge payload', async function () {
- const attributes = { name: 'audio_with_preview', previewfile: 'custom-preview.jpg', fixture: 'sample.ogg' }
- await server.videos.upload({ attributes, mode: 'legacy' })
-
- await waitJobs([ server ])
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'vod-audio-merge-transcoding' })
-
- await server.runnerJobs.success({
- jobUUID: job.uuid,
- jobToken: job.jobToken,
- payload: { hello: 'video_short.mp4' } as any,
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('Video studio', function () {
-
- it('Should fail with an invalid video studio transcoding payload', async function () {
- await server.runnerJobs.success({
- jobUUID: studioAcceptedJob.uuid,
- jobToken: studioAcceptedJob.jobToken,
- payload: { hello: 'video_short.mp4' } as any,
- runnerToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
- })
-
- describe('Job files', function () {
-
- describe('Check video param for common job file routes', function () {
-
- async function fetchFiles (options: {
- videoUUID?: string
- expectedStatus: HttpStatusCode
- }) {
- await fetchVideoInputFiles({ videoUUID, ...options, jobToken, jobUUID, runnerToken })
-
- await fetchStudioFiles({
- videoUUID: videoStudioUUID,
-
- ...options,
-
- jobToken: studioAcceptedJob.jobToken,
- jobUUID: studioAcceptedJob.uuid,
- runnerToken,
- studioFile
- })
- }
-
- it('Should fail with an invalid video id', async function () {
- await fetchFiles({
- videoUUID: 'a',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown video id', async function () {
- const videoUUID = '910ec12a-d9e6-458b-a274-0abb655f9464'
-
- await fetchFiles({
- videoUUID,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a video id not associated to this job', async function () {
- await fetchFiles({
- videoUUID: videoUUID2,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await fetchFiles({ expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('Video studio tasks file routes', function () {
-
- it('Should fail with an invalid studio filename', async function () {
- await fetchStudioFiles({
- videoUUID: videoStudioUUID,
- jobUUID: studioAcceptedJob.uuid,
- runnerToken,
- jobToken: studioAcceptedJob.jobToken,
- studioFile: 'toto',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/search.ts b/server/tests/api/check-params/search.ts
deleted file mode 100644
index b04d30b7f..000000000
--- a/server/tests/api/check-params/search.ts
+++ /dev/null
@@ -1,272 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-function updateSearchIndex (server: PeerTubeServer, enabled: boolean, disableLocalSearch = false) {
- return server.config.updateCustomSubConfig({
- newConfig: {
- search: {
- searchIndex: {
- enabled,
- disableLocalSearch
- }
- }
- }
- })
-}
-
-describe('Test videos API validator', function () {
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- })
-
- describe('When searching videos', function () {
- const path = '/api/v1/search/videos/'
-
- const query = {
- search: 'coucou'
- }
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, null, query)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, null, query)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, null, query)
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should fail with an invalid category', async function () {
- const customQuery1 = { ...query, categoryOneOf: [ 'aa', 'b' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery2 = { ...query, categoryOneOf: 'a' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with a valid category', async function () {
- const customQuery1 = { ...query, categoryOneOf: [ 1, 7 ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery2 = { ...query, categoryOneOf: 1 }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should fail with an invalid licence', async function () {
- const customQuery1 = { ...query, licenceOneOf: [ 'aa', 'b' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery2 = { ...query, licenceOneOf: 'a' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with a valid licence', async function () {
- const customQuery1 = { ...query, licenceOneOf: [ 1, 2 ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery2 = { ...query, licenceOneOf: 1 }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should succeed with a valid language', async function () {
- const customQuery1 = { ...query, languageOneOf: [ 'fr', 'en' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery2 = { ...query, languageOneOf: 'fr' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should succeed with valid tags', async function () {
- const customQuery1 = { ...query, tagsOneOf: [ 'tag1', 'tag2' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery2 = { ...query, tagsOneOf: 'tag1' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery3 = { ...query, tagsAllOf: [ 'tag1', 'tag2' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery3, expectedStatus: HttpStatusCode.OK_200 })
-
- const customQuery4 = { ...query, tagsAllOf: 'tag1' }
- await makeGetRequest({ url: server.url, path, query: customQuery4, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should fail with invalid durations', async function () {
- const customQuery1 = { ...query, durationMin: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery2 = { ...query, durationMax: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with invalid dates', async function () {
- const customQuery1 = { ...query, startDate: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery2 = { ...query, endDate: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery2, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery3 = { ...query, originallyPublishedStartDate: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery3, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- const customQuery4 = { ...query, originallyPublishedEndDate: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery4, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an invalid host', async function () {
- const customQuery = { ...query, host: '6565' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with a host', async function () {
- const customQuery = { ...query, host: 'example.com' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should fail with invalid uuids', async function () {
- const customQuery = { ...query, uuids: [ '6565', 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with valid uuids', async function () {
- const customQuery = { ...query, uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When searching video playlists', function () {
- const path = '/api/v1/search/video-playlists/'
-
- const query = {
- search: 'coucou',
- host: 'example.com'
- }
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, null, query)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, null, query)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, null, query)
- })
-
- it('Should fail with an invalid host', async function () {
- await makeGetRequest({ url: server.url, path, query: { ...query, host: '6565' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with invalid uuids', async function () {
- const customQuery = { ...query, uuids: [ '6565', 'dfd70b83-639f-4980-94af-304a56ab4b35' ] }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When searching video channels', function () {
- const path = '/api/v1/search/video-channels/'
-
- const query = {
- search: 'coucou',
- host: 'example.com'
- }
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, null, query)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, null, query)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, null, query)
- })
-
- it('Should fail with an invalid host', async function () {
- await makeGetRequest({ url: server.url, path, query: { ...query, host: '6565' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with invalid handles', async function () {
- await makeGetRequest({ url: server.url, path, query: { ...query, handles: [ '' ] }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, query, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('Search target', function () {
-
- it('Should fail/succeed depending on the search target', async function () {
- const query = { search: 'coucou' }
- const paths = [
- '/api/v1/search/video-playlists/',
- '/api/v1/search/video-channels/',
- '/api/v1/search/videos/'
- ]
-
- for (const path of paths) {
- {
- const customQuery = { ...query, searchTarget: 'hello' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
-
- {
- const customQuery = { ...query, searchTarget: undefined }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- {
- const customQuery = { ...query, searchTarget: 'local' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- {
- const customQuery = { ...query, searchTarget: 'search-index' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
-
- await updateSearchIndex(server, true, true)
-
- {
- const customQuery = { ...query, searchTarget: 'search-index' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- await updateSearchIndex(server, true, false)
-
- {
- const customQuery = { ...query, searchTarget: 'local' }
- await makeGetRequest({ url: server.url, path, query: customQuery, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- await updateSearchIndex(server, false, false)
- }
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/services.ts b/server/tests/api/check-params/services.ts
deleted file mode 100644
index d45868f36..000000000
--- a/server/tests/api/check-params/services.ts
+++ /dev/null
@@ -1,195 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, VideoCreateResult, VideoPlaylistCreateResult, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test services API validators', function () {
- let server: PeerTubeServer
- let playlistUUID: string
-
- let privateVideo: VideoCreateResult
- let unlistedVideo: VideoCreateResult
-
- let privatePlaylist: VideoPlaylistCreateResult
- let unlistedPlaylist: VideoPlaylistCreateResult
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(60000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- server.store.videoCreated = await server.videos.upload({ attributes: { name: 'my super name' } })
-
- privateVideo = await server.videos.quickUpload({ name: 'private', privacy: VideoPrivacy.PRIVATE })
- unlistedVideo = await server.videos.quickUpload({ name: 'unlisted', privacy: VideoPrivacy.UNLISTED })
-
- {
- const created = await server.playlists.create({
- attributes: {
- displayName: 'super playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id
- }
- })
-
- playlistUUID = created.uuid
-
- privatePlaylist = await server.playlists.create({
- attributes: {
- displayName: 'private',
- privacy: VideoPlaylistPrivacy.PRIVATE,
- videoChannelId: server.store.channel.id
- }
- })
-
- unlistedPlaylist = await server.playlists.create({
- attributes: {
- displayName: 'unlisted',
- privacy: VideoPlaylistPrivacy.UNLISTED,
- videoChannelId: server.store.channel.id
- }
- })
- }
- })
-
- describe('Test oEmbed API validators', function () {
-
- it('Should fail with an invalid url', async function () {
- const embedUrl = 'hello.com'
- await checkParamEmbed(server, embedUrl)
- })
-
- it('Should fail with an invalid host', async function () {
- const embedUrl = 'http://hello.com/videos/watch/' + server.store.videoCreated.uuid
- await checkParamEmbed(server, embedUrl)
- })
-
- it('Should fail with an invalid element id', async function () {
- const embedUrl = `${server.url}/videos/watch/blabla`
- await checkParamEmbed(server, embedUrl)
- })
-
- it('Should fail with an unknown element', async function () {
- const embedUrl = `${server.url}/videos/watch/88fc0165-d1f0-4a35-a51a-3b47f668689c`
- await checkParamEmbed(server, embedUrl, HttpStatusCode.NOT_FOUND_404)
- })
-
- it('Should fail with an invalid path', async function () {
- const embedUrl = `${server.url}/videos/watchs/${server.store.videoCreated.uuid}`
-
- await checkParamEmbed(server, embedUrl)
- })
-
- it('Should fail with an invalid max height', async function () {
- const embedUrl = `${server.url}/videos/watch/${server.store.videoCreated.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxheight: 'hello' })
- })
-
- it('Should fail with an invalid max width', async function () {
- const embedUrl = `${server.url}/videos/watch/${server.store.videoCreated.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { maxwidth: 'hello' })
- })
-
- it('Should fail with an invalid format', async function () {
- const embedUrl = `${server.url}/videos/watch/${server.store.videoCreated.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.BAD_REQUEST_400, { format: 'blabla' })
- })
-
- it('Should fail with a non supported format', async function () {
- const embedUrl = `${server.url}/videos/watch/${server.store.videoCreated.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.NOT_IMPLEMENTED_501, { format: 'xml' })
- })
-
- it('Should fail with a private video', async function () {
- const embedUrl = `${server.url}/videos/watch/${privateVideo.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.FORBIDDEN_403)
- })
-
- it('Should fail with an unlisted video with the int id', async function () {
- const embedUrl = `${server.url}/videos/watch/${unlistedVideo.id}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.FORBIDDEN_403)
- })
-
- it('Should succeed with an unlisted video using the uuid id', async function () {
- for (const uuid of [ unlistedVideo.uuid, unlistedVideo.shortUUID ]) {
- const embedUrl = `${server.url}/videos/watch/${uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.OK_200)
- }
- })
-
- it('Should fail with a private playlist', async function () {
- const embedUrl = `${server.url}/videos/watch/playlist/${privatePlaylist.uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.FORBIDDEN_403)
- })
-
- it('Should fail with an unlisted playlist using the int id', async function () {
- const embedUrl = `${server.url}/videos/watch/playlist/${unlistedPlaylist.id}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.FORBIDDEN_403)
- })
-
- it('Should succeed with an unlisted playlist using the uuid id', async function () {
- for (const uuid of [ unlistedPlaylist.uuid, unlistedPlaylist.shortUUID ]) {
- const embedUrl = `${server.url}/videos/watch/playlist/${uuid}`
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.OK_200)
- }
- })
-
- it('Should succeed with the correct params with a video', async function () {
- const embedUrl = `${server.url}/videos/watch/${server.store.videoCreated.uuid}`
- const query = {
- format: 'json',
- maxheight: 400,
- maxwidth: 400
- }
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.OK_200, query)
- })
-
- it('Should succeed with the correct params with a playlist', async function () {
- const embedUrl = `${server.url}/videos/watch/playlist/${playlistUUID}`
- const query = {
- format: 'json',
- maxheight: 400,
- maxwidth: 400
- }
-
- await checkParamEmbed(server, embedUrl, HttpStatusCode.OK_200, query)
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
-
-function checkParamEmbed (server: PeerTubeServer, embedUrl: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400, query = {}) {
- const path = '/services/oembed'
-
- return makeGetRequest({
- url: server.url,
- path,
- query: Object.assign(query, { url: embedUrl }),
- expectedStatus
- })
-}
diff --git a/server/tests/api/check-params/transcoding.ts b/server/tests/api/check-params/transcoding.ts
deleted file mode 100644
index d5899e11b..000000000
--- a/server/tests/api/check-params/transcoding.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, UserRole } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test transcoding API validators', function () {
- let servers: PeerTubeServer[]
-
- let userToken: string
- let moderatorToken: string
-
- let remoteId: string
- let validId: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER)
- moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR)
-
- {
- const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' })
- remoteId = uuid
- }
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'both 1' })
- validId = uuid
- }
-
- await waitJobs(servers)
-
- await servers[0].config.enableTranscoding()
- })
-
- it('Should not run transcoding of a unknown video', async function () {
- await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'hls', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'web-video', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should not run transcoding of a remote video', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'hls', expectedStatus })
- await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'web-video', expectedStatus })
- })
-
- it('Should not run transcoding by a non admin user', async function () {
- const expectedStatus = HttpStatusCode.FORBIDDEN_403
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', token: userToken, expectedStatus })
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', token: moderatorToken, expectedStatus })
- })
-
- it('Should not run transcoding without transcoding type', async function () {
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not run transcoding with an incorrect transcoding type', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'toto' as any, expectedStatus })
- })
-
- it('Should not run transcoding if the instance disabled it', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await servers[0].config.disableTranscoding()
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', expectedStatus })
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
- })
-
- it('Should run transcoding', async function () {
- this.timeout(120_000)
-
- await servers[0].config.enableTranscoding()
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls' })
- await waitJobs(servers)
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', forceTranscoding: true })
- await waitJobs(servers)
- })
-
- it('Should not run transcoding on a video that is already being transcoded if forceTranscoding is not set', async function () {
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video' })
-
- const expectedStatus = HttpStatusCode.CONFLICT_409
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
-
- await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', forceTranscoding: true })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/two-factor.ts b/server/tests/api/check-params/two-factor.ts
deleted file mode 100644
index f8365f1b5..000000000
--- a/server/tests/api/check-params/two-factor.ts
+++ /dev/null
@@ -1,288 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, TwoFactorCommand } from '@shared/server-commands'
-
-describe('Test two factor API validators', function () {
- let server: PeerTubeServer
-
- let rootId: number
- let rootPassword: string
- let rootRequestToken: string
- let rootOTPToken: string
-
- let userId: number
- let userToken = ''
- let userPassword: string
- let userRequestToken: string
- let userOTPToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- {
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- }
-
- {
- const result = await server.users.generate('user1')
- userToken = result.token
- userId = result.userId
- userPassword = result.password
- }
-
- {
- const { id } = await server.users.getMyInfo()
- rootId = id
- rootPassword = server.store.user.password
- }
- })
-
- describe('When requesting two factor', function () {
-
- it('Should fail with an unknown user id', async function () {
- await server.twoFactor.request({ userId: 42, currentPassword: rootPassword, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an invalid user id', async function () {
- await server.twoFactor.request({
- userId: 'invalid' as any,
- currentPassword: rootPassword,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to request another user two factor without the appropriate rights', async function () {
- await server.twoFactor.request({
- userId: rootId,
- token: userToken,
- currentPassword: userPassword,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to request another user two factor with the appropriate rights', async function () {
- await server.twoFactor.request({ userId, currentPassword: rootPassword })
- })
-
- it('Should fail to request two factor without a password', async function () {
- await server.twoFactor.request({
- userId,
- token: userToken,
- currentPassword: undefined,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to request two factor with an incorrect password', async function () {
- await server.twoFactor.request({
- userId,
- token: userToken,
- currentPassword: rootPassword,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to request two factor without a password when targeting a remote user with an admin account', async function () {
- await server.twoFactor.request({ userId })
- })
-
- it('Should fail to request two factor without a password when targeting myself with an admin account', async function () {
- await server.twoFactor.request({ userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.twoFactor.request({ userId: rootId, currentPassword: 'bad', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed to request my two factor auth', async function () {
- {
- const { otpRequest } = await server.twoFactor.request({ userId, token: userToken, currentPassword: userPassword })
- userRequestToken = otpRequest.requestToken
- userOTPToken = TwoFactorCommand.buildOTP({ secret: otpRequest.secret }).generate()
- }
-
- {
- const { otpRequest } = await server.twoFactor.request({ userId: rootId, currentPassword: rootPassword })
- rootRequestToken = otpRequest.requestToken
- rootOTPToken = TwoFactorCommand.buildOTP({ secret: otpRequest.secret }).generate()
- }
- })
- })
-
- describe('When confirming two factor request', function () {
-
- it('Should fail with an unknown user id', async function () {
- await server.twoFactor.confirmRequest({
- userId: 42,
- requestToken: rootRequestToken,
- otpToken: rootOTPToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an invalid user id', async function () {
- await server.twoFactor.confirmRequest({
- userId: 'invalid' as any,
- requestToken: rootRequestToken,
- otpToken: rootOTPToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to confirm another user two factor request without the appropriate rights', async function () {
- await server.twoFactor.confirmRequest({
- userId: rootId,
- token: userToken,
- requestToken: rootRequestToken,
- otpToken: rootOTPToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail without request token', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: undefined,
- otpToken: userOTPToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an invalid request token', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: 'toto',
- otpToken: userOTPToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with request token of another user', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: rootRequestToken,
- otpToken: userOTPToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail without an otp token', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: userRequestToken,
- otpToken: undefined,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad otp token', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: userRequestToken,
- otpToken: '123456',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to confirm another user two factor request with the appropriate rights', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- requestToken: userRequestToken,
- otpToken: userOTPToken
- })
-
- // Reinit
- await server.twoFactor.disable({ userId, currentPassword: rootPassword })
- })
-
- it('Should succeed to confirm my two factor request', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- token: userToken,
- requestToken: userRequestToken,
- otpToken: userOTPToken
- })
- })
-
- it('Should fail to confirm again two factor request', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- token: userToken,
- requestToken: userRequestToken,
- otpToken: userOTPToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- describe('When disabling two factor', function () {
-
- it('Should fail with an unknown user id', async function () {
- await server.twoFactor.disable({
- userId: 42,
- currentPassword: rootPassword,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an invalid user id', async function () {
- await server.twoFactor.disable({
- userId: 'invalid' as any,
- currentPassword: rootPassword,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to disable another user two factor without the appropriate rights', async function () {
- await server.twoFactor.disable({
- userId: rootId,
- token: userToken,
- currentPassword: userPassword,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail to disable two factor with an incorrect password', async function () {
- await server.twoFactor.disable({
- userId,
- token: userToken,
- currentPassword: rootPassword,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to disable two factor without a password when targeting a remote user with an admin account', async function () {
- await server.twoFactor.disable({ userId })
- await server.twoFactor.requestAndConfirm({ userId })
- })
-
- it('Should fail to disable two factor without a password when targeting myself with an admin account', async function () {
- await server.twoFactor.disable({ userId: rootId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.twoFactor.disable({ userId: rootId, currentPassword: 'bad', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed to disable another user two factor with the appropriate rights', async function () {
- await server.twoFactor.disable({ userId, currentPassword: rootPassword })
-
- await server.twoFactor.requestAndConfirm({ userId })
- })
-
- it('Should succeed to update my two factor auth', async function () {
- await server.twoFactor.disable({ userId, token: userToken, currentPassword: userPassword })
- })
-
- it('Should fail to disable again two factor', async function () {
- await server.twoFactor.disable({
- userId,
- token: userToken,
- currentPassword: userPassword,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/upload-quota.ts b/server/tests/api/check-params/upload-quota.ts
deleted file mode 100644
index 06698c056..000000000
--- a/server/tests/api/check-params/upload-quota.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { randomInt } from '@shared/core-utils'
-import { HttpStatusCode, VideoImportState, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- VideosCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test upload quota', function () {
- let server: PeerTubeServer
- let rootId: number
- let command: VideosCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- const user = await server.users.getMyInfo()
- rootId = user.id
-
- await server.users.update({ userId: rootId, videoQuota: 42 })
-
- command = server.videos
- })
-
- describe('When having a video quota', function () {
-
- it('Should fail with a registered user having too many videos with legacy upload', async function () {
- this.timeout(120000)
-
- const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
- await server.registrations.register(user)
- const userToken = await server.login.getAccessToken(user)
-
- const attributes = { fixture: 'video_short2.webm' }
- for (let i = 0; i < 5; i++) {
- await command.upload({ token: userToken, attributes })
- }
-
- await command.upload({ token: userToken, attributes, expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
- })
-
- it('Should fail with a registered user having too many videos with resumable upload', async function () {
- this.timeout(120000)
-
- const user = { username: 'registered' + randomInt(1, 1500), password: 'password' }
- await server.registrations.register(user)
- const userToken = await server.login.getAccessToken(user)
-
- const attributes = { fixture: 'video_short2.webm' }
- for (let i = 0; i < 5; i++) {
- await command.upload({ token: userToken, attributes })
- }
-
- await command.upload({ token: userToken, attributes, expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
- })
-
- it('Should fail to import with HTTP/Torrent/magnet', async function () {
- this.timeout(120_000)
-
- const baseAttributes = {
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- await server.imports.importVideo({ attributes: { ...baseAttributes, targetUrl: FIXTURE_URLS.goodVideo } })
- await server.imports.importVideo({ attributes: { ...baseAttributes, magnetUri: FIXTURE_URLS.magnet } })
- await server.imports.importVideo({ attributes: { ...baseAttributes, torrentfile: 'video-720p.torrent' as any } })
-
- await waitJobs([ server ])
-
- const { total, data: videoImports } = await server.imports.getMyVideoImports()
- expect(total).to.equal(3)
-
- expect(videoImports).to.have.lengthOf(3)
-
- for (const videoImport of videoImports) {
- expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
- expect(videoImport.error).not.to.be.undefined
- expect(videoImport.error).to.contain('user video quota is exceeded')
- }
- })
- })
-
- describe('When having a daily video quota', function () {
-
- it('Should fail with a user having too many videos daily', async function () {
- await server.users.update({ userId: rootId, videoQuotaDaily: 42 })
-
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
- })
- })
-
- describe('When having an absolute and daily video quota', function () {
- it('Should fail if exceeding total quota', async function () {
- await server.users.update({
- userId: rootId,
- videoQuota: 42,
- videoQuotaDaily: 1024 * 1024 * 1024
- })
-
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
- })
-
- it('Should fail if exceeding daily quota', async function () {
- await server.users.update({
- userId: rootId,
- videoQuota: 1024 * 1024 * 1024,
- videoQuotaDaily: 42
- })
-
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'legacy' })
- await command.upload({ expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413, mode: 'resumable' })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/user-notifications.ts b/server/tests/api/check-params/user-notifications.ts
deleted file mode 100644
index 6a588e446..000000000
--- a/server/tests/api/check-params/user-notifications.ts
+++ /dev/null
@@ -1,290 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { io } from 'socket.io-client'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, UserNotificationSetting, UserNotificationSettingValue } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test user notifications API validators', function () {
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- })
-
- describe('When listing my notifications', function () {
- const path = '/api/v1/users/me/notifications'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect unread parameter', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: {
- unread: 'toto'
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When marking as read my notifications', function () {
- const path = '/api/v1/users/me/notifications/read'
-
- it('Should fail with wrong ids parameters', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: {
- ids: [ 'hello' ]
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: {
- ids: [ ]
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: {
- ids: 5
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: {
- ids: [ 5 ]
- },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: {
- ids: [ 5 ]
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When marking as read my notifications', function () {
- const path = '/api/v1/users/me/notifications/read-all'
-
- it('Should fail with a non authenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When updating my notification settings', function () {
- const path = '/api/v1/users/me/notification-settings'
- const correctFields: UserNotificationSetting = {
- newVideoFromSubscription: UserNotificationSettingValue.WEB,
- newCommentOnMyVideo: UserNotificationSettingValue.WEB,
- abuseAsModerator: UserNotificationSettingValue.WEB,
- videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB,
- blacklistOnMyVideo: UserNotificationSettingValue.WEB,
- myVideoImportFinished: UserNotificationSettingValue.WEB,
- myVideoPublished: UserNotificationSettingValue.WEB,
- commentMention: UserNotificationSettingValue.WEB,
- newFollow: UserNotificationSettingValue.WEB,
- newUserRegistration: UserNotificationSettingValue.WEB,
- newInstanceFollower: UserNotificationSettingValue.WEB,
- autoInstanceFollowing: UserNotificationSettingValue.WEB,
- abuseNewMessage: UserNotificationSettingValue.WEB,
- abuseStateChange: UserNotificationSettingValue.WEB,
- newPeerTubeVersion: UserNotificationSettingValue.WEB,
- myVideoStudioEditionFinished: UserNotificationSettingValue.WEB,
- newPluginVersion: UserNotificationSettingValue.WEB
- }
-
- it('Should fail with missing fields', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { newVideoFromSubscription: UserNotificationSettingValue.WEB },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with incorrect field values', async function () {
- {
- const fields = { ...correctFields, newCommentOnMyVideo: 15 }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
-
- {
- const fields = { ...correctFields, newCommentOnMyVideo: 'toto' }
-
- await makePutBodyRequest({
- url: server.url,
- path,
- fields,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- }
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- fields: correctFields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: correctFields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When connecting to my notification socket', function () {
-
- it('Should fail with no token', function (next) {
- const socket = io(`${server.url}/user-notifications`, { reconnection: false })
-
- socket.once('connect_error', function () {
- socket.disconnect()
- next()
- })
-
- socket.on('connect', () => {
- socket.disconnect()
- next(new Error('Connected with a missing token.'))
- })
- })
-
- it('Should fail with an invalid token', function (next) {
- const socket = io(`${server.url}/user-notifications`, {
- query: { accessToken: 'bad_access_token' },
- reconnection: false
- })
-
- socket.once('connect_error', function () {
- socket.disconnect()
- next()
- })
-
- socket.on('connect', () => {
- socket.disconnect()
- next(new Error('Connected with an invalid token.'))
- })
- })
-
- it('Should success with the correct token', function (next) {
- const socket = io(`${server.url}/user-notifications`, {
- query: { accessToken: server.accessToken },
- reconnection: false
- })
-
- function errorListener (err) {
- next(new Error('Error in connection: ' + err))
- }
-
- socket.on('connect_error', errorListener)
-
- socket.once('connect', async () => {
- socket.disconnect()
-
- await wait(500)
- next()
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/user-subscriptions.ts b/server/tests/api/check-params/user-subscriptions.ts
deleted file mode 100644
index c4922c7a2..000000000
--- a/server/tests/api/check-params/user-subscriptions.ts
+++ /dev/null
@@ -1,298 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-import { checkBadStartPagination, checkBadCountPagination, checkBadSortPagination } from '@server/tests/shared'
-
-describe('Test user subscriptions API validators', function () {
- const path = '/api/v1/users/me/subscriptions'
- let server: PeerTubeServer
- let userAccessToken = ''
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- })
-
- describe('When listing my subscriptions', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When listing my subscriptions videos', function () {
- const path = '/api/v1/users/me/subscriptions/videos'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When adding a subscription', function () {
- it('Should fail with a non authenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- fields: { uri: 'user1_channel@' + server.host },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with bad URIs', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { uri: 'root' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { uri: 'root@' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { uri: 'root@hello@' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- this.timeout(20000)
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: { uri: 'user1_channel@' + server.host },
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-
- await waitJobs([ server ])
- })
- })
-
- describe('When getting a subscription', function () {
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + '/user1_channel@' + server.host,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with bad URIs', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + '/root',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url: server.url,
- path: path + '/root@',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url: server.url,
- path: path + '/root@hello@',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown subscription', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + '/root1@' + server.host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + '/user1_channel@' + server.host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When checking if subscriptions exist', function () {
- const existPath = path + '/exist'
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path: existPath,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with bad URIs', async function () {
- await makeGetRequest({
- url: server.url,
- path: existPath,
- query: { uris: 'toto' },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url: server.url,
- path: existPath,
- query: { 'uris[]': 1 },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path: existPath,
- query: { 'uris[]': 'coucou@' + server.host },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When removing a subscription', function () {
- it('Should fail with a non authenticated user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1_channel@' + server.host,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with bad URIs', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/root',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeDeleteRequest({
- url: server.url,
- path: path + '/root@',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeDeleteRequest({
- url: server.url,
- path: path + '/root@hello@',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown subscription', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/root1@' + server.host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '/user1_channel@' + server.host,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/users-admin.ts b/server/tests/api/check-params/users-admin.ts
deleted file mode 100644
index 819da0bb2..000000000
--- a/server/tests/api/check-params/users-admin.ts
+++ /dev/null
@@ -1,456 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, MockSmtpServer } from '@server/tests/shared'
-import { omit } from '@shared/core-utils'
-import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createSingleServer,
- killallServers,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test users admin API validators', function () {
- const path = '/api/v1/users/'
- let userId: number
- let rootId: number
- let moderatorId: number
- let server: PeerTubeServer
- let userToken = ''
- let moderatorToken = ''
- let emailPort: number
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- const emails: object[] = []
- emailPort = await MockSmtpServer.Instance.collectEmails(emails)
-
- {
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- }
-
- {
- const result = await server.users.generate('user1')
- userToken = result.token
- userId = result.userId
- }
-
- {
- const result = await server.users.generate('moderator1', UserRole.MODERATOR)
- moderatorToken = result.token
- }
-
- {
- const result = await server.users.generate('moderator2', UserRole.MODERATOR)
- moderatorId = result.userId
- }
- })
-
- describe('When listing users', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- describe('When adding a new user', function () {
- const baseCorrectParams = {
- username: 'user2',
- email: 'test@example.com',
- password: 'my super password',
- videoQuota: -1,
- videoQuotaDaily: -1,
- role: UserRole.USER,
- adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
- }
-
- it('Should fail with a too small username', async function () {
- const fields = { ...baseCorrectParams, username: '' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a too long username', async function () {
- const fields = { ...baseCorrectParams, username: 'super'.repeat(50) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a not lowercase username', async function () {
- const fields = { ...baseCorrectParams, username: 'Toto' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect username', async function () {
- const fields = { ...baseCorrectParams, username: 'my username' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a missing email', async function () {
- const fields = omit(baseCorrectParams, [ 'email' ])
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid email', async function () {
- const fields = { ...baseCorrectParams, email: 'test_example.com' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a too small password', async function () {
- const fields = { ...baseCorrectParams, password: 'bla' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a too long password', async function () {
- const fields = { ...baseCorrectParams, password: 'super'.repeat(61) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with empty password and no smtp configured', async function () {
- const fields = { ...baseCorrectParams, password: '' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should succeed with no password on a server with smtp enabled', async function () {
- this.timeout(20000)
-
- await killallServers([ server ])
-
- await server.run(ConfigCommand.getEmailOverrideConfig(emailPort))
-
- const fields = {
- ...baseCorrectParams,
-
- password: '',
- username: 'create_password',
- email: 'create_password@example.com'
- }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should fail with invalid admin flags', async function () {
- const fields = { ...baseCorrectParams, adminFlags: 'toto' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an non authenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- token: 'super token',
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail if we add a user with the same username', async function () {
- const fields = { ...baseCorrectParams, username: 'user1' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail if we add a user with the same email', async function () {
- const fields = { ...baseCorrectParams, email: 'user1@example.com' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail with an invalid videoQuota', async function () {
- const fields = { ...baseCorrectParams, videoQuota: -5 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid videoQuotaDaily', async function () {
- const fields = { ...baseCorrectParams, videoQuotaDaily: -7 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail without a user role', async function () {
- const fields = omit(baseCorrectParams, [ 'role' ])
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid user role', async function () {
- const fields = { ...baseCorrectParams, role: 88989 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a "peertube" username', async function () {
- const fields = { ...baseCorrectParams, username: 'peertube' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should fail to create a moderator or an admin with a moderator', async function () {
- for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
- const fields = { ...baseCorrectParams, role }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: moderatorToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
- })
-
- it('Should succeed to create a user with a moderator', async function () {
- const fields = { ...baseCorrectParams, username: 'a4656', email: 'a4656@example.com', role: UserRole.USER }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: moderatorToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should fail with a non admin user', async function () {
- const user = { username: 'user1' }
- userToken = await server.login.getAccessToken(user)
-
- const fields = {
- username: 'user3',
- email: 'test@example.com',
- password: 'my super password',
- videoQuota: 42000000
- }
- await makePostBodyRequest({ url: server.url, path, token: userToken, fields, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
- })
-
- describe('When getting a user', function () {
-
- it('Should fail with an non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + userId,
- token: 'super token',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({ url: server.url, path, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When updating a user', function () {
-
- it('Should fail with an invalid email attribute', async function () {
- const fields = {
- email: 'blabla'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid emailVerified attribute', async function () {
- const fields = {
- emailVerified: 'yes'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid videoQuota attribute', async function () {
- const fields = {
- videoQuota: -90
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with an invalid user role attribute', async function () {
- const fields = {
- role: 54878
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with a too small password', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'bla'
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with a too long password', async function () {
- const fields = {
- currentPassword: 'password',
- password: 'super'.repeat(61)
- }
-
- await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
- })
-
- it('Should fail with an non authenticated user', async function () {
- const fields = {
- videoQuota: 42
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + userId,
- token: 'super token',
- fields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail when updating root role', async function () {
- const fields = {
- role: UserRole.MODERATOR
- }
-
- await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
- })
-
- it('Should fail with invalid admin flags', async function () {
- const fields = { adminFlags: 'toto' }
-
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail to update an admin with a moderator', async function () {
- const fields = {
- videoQuota: 42
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + moderatorId,
- token: moderatorToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to update a user with a moderator', async function () {
- const fields = {
- videoQuota: 42
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + userId,
- token: moderatorToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should succeed with the correct params', async function () {
- const fields = {
- email: 'email@example.com',
- emailVerified: true,
- videoQuota: 42,
- role: UserRole.USER
- }
-
- await makePutBodyRequest({
- url: server.url,
- path: path + userId,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/users-emails.ts b/server/tests/api/check-params/users-emails.ts
deleted file mode 100644
index 6ebcc8ffe..000000000
--- a/server/tests/api/check-params/users-emails.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { HttpStatusCode, UserRole } from '@shared/models'
-import { cleanupTests, createSingleServer, makePostBodyRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test users API validators', function () {
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {
- rates_limit: {
- ask_send_email: {
- max: 10
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
- await server.config.enableSignup(true)
-
- await server.users.generate('moderator2', UserRole.MODERATOR)
-
- await server.registrations.requestRegistration({
- username: 'request1',
- registrationReason: 'tt'
- })
- })
-
- describe('When asking a password reset', function () {
- const path = '/api/v1/users/ask-reset-password'
-
- it('Should fail with a missing email', async function () {
- const fields = {}
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should fail with an invalid email', async function () {
- const fields = { email: 'hello' }
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should success with the correct params', async function () {
- const fields = { email: 'admin@example.com' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When asking for an account verification email', function () {
- const path = '/api/v1/users/ask-send-verify-email'
-
- it('Should fail with a missing email', async function () {
- const fields = {}
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should fail with an invalid email', async function () {
- const fields = { email: 'hello' }
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should succeed with the correct params', async function () {
- const fields = { email: 'admin@example.com' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When asking for a registration verification email', function () {
- const path = '/api/v1/users/registrations/ask-send-verify-email'
-
- it('Should fail with a missing email', async function () {
- const fields = {}
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should fail with an invalid email', async function () {
- const fields = { email: 'hello' }
-
- await makePostBodyRequest({ url: server.url, path, fields })
- })
-
- it('Should succeed with the correct params', async function () {
- const fields = { email: 'request1@example.com' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-blacklist.ts b/server/tests/api/check-params/video-blacklist.ts
deleted file mode 100644
index 8e9f61596..000000000
--- a/server/tests/api/check-params/video-blacklist.ts
+++ /dev/null
@@ -1,292 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode, VideoBlacklistType } from '@shared/models'
-import {
- BlacklistCommand,
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video blacklist API validators', function () {
- let servers: PeerTubeServer[]
- let notBlacklistedVideoId: string
- let remoteVideoUUID: string
- let userAccessToken1 = ''
- let userAccessToken2 = ''
- let command: BlacklistCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await doubleFollow(servers[0], servers[1])
-
- {
- const username = 'user1'
- const password = 'my super password'
- await servers[0].users.create({ username, password })
- userAccessToken1 = await servers[0].login.getAccessToken({ username, password })
- }
-
- {
- const username = 'user2'
- const password = 'my super password'
- await servers[0].users.create({ username, password })
- userAccessToken2 = await servers[0].login.getAccessToken({ username, password })
- }
-
- {
- servers[0].store.videoCreated = await servers[0].videos.upload({ token: userAccessToken1 })
- }
-
- {
- const { uuid } = await servers[0].videos.upload()
- notBlacklistedVideoId = uuid
- }
-
- {
- const { uuid } = await servers[1].videos.upload()
- remoteVideoUUID = uuid
- }
-
- await waitJobs(servers)
-
- command = servers[0].blacklist
- })
-
- describe('When adding a video in blacklist', function () {
- const basePath = '/api/v1/videos/'
-
- it('Should fail with nothing', async function () {
- const path = basePath + servers[0].store.videoCreated + '/blacklist'
- const fields = {}
- await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
- })
-
- it('Should fail with a wrong video', async function () {
- const wrongPath = '/api/v1/videos/blabla/blacklist'
- const fields = {}
- await makePostBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields })
- })
-
- it('Should fail with a non authenticated user', async function () {
- const path = basePath + servers[0].store.videoCreated + '/blacklist'
- const fields = {}
- await makePostBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a non admin user', async function () {
- const path = basePath + servers[0].store.videoCreated + '/blacklist'
- const fields = {}
- await makePostBodyRequest({
- url: servers[0].url,
- path,
- token: userAccessToken2,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid reason', async function () {
- const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
- const fields = { reason: 'a'.repeat(305) }
-
- await makePostBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
- })
-
- it('Should fail to unfederate a remote video', async function () {
- const path = basePath + remoteVideoUUID + '/blacklist'
- const fields = { unfederate: true }
-
- await makePostBodyRequest({
- url: servers[0].url,
- path,
- token: servers[0].accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should succeed with the correct params', async function () {
- const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
- const fields = {}
-
- await makePostBodyRequest({
- url: servers[0].url,
- path,
- token: servers[0].accessToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When updating a video in blacklist', function () {
- const basePath = '/api/v1/videos/'
-
- it('Should fail with a wrong video', async function () {
- const wrongPath = '/api/v1/videos/blabla/blacklist'
- const fields = {}
- await makePutBodyRequest({ url: servers[0].url, path: wrongPath, token: servers[0].accessToken, fields })
- })
-
- it('Should fail with a video not blacklisted', async function () {
- const path = '/api/v1/videos/' + notBlacklistedVideoId + '/blacklist'
- const fields = {}
- await makePutBodyRequest({
- url: servers[0].url,
- path,
- token: servers[0].accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a non authenticated user', async function () {
- const path = basePath + servers[0].store.videoCreated + '/blacklist'
- const fields = {}
- await makePutBodyRequest({ url: servers[0].url, path, token: 'hello', fields, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a non admin user', async function () {
- const path = basePath + servers[0].store.videoCreated + '/blacklist'
- const fields = {}
- await makePutBodyRequest({
- url: servers[0].url,
- path,
- token: userAccessToken2,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid reason', async function () {
- const path = basePath + servers[0].store.videoCreated.uuid + '/blacklist'
- const fields = { reason: 'a'.repeat(305) }
-
- await makePutBodyRequest({ url: servers[0].url, path, token: servers[0].accessToken, fields })
- })
-
- it('Should succeed with the correct params', async function () {
- const path = basePath + servers[0].store.videoCreated.shortUUID + '/blacklist'
- const fields = { reason: 'hello' }
-
- await makePutBodyRequest({
- url: servers[0].url,
- path,
- token: servers[0].accessToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When getting blacklisted video', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await servers[0].videos.get({ id: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another user', async function () {
- await servers[0].videos.getWithToken({
- token: userAccessToken2,
- id: servers[0].store.videoCreated.uuid,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the owner authenticated user', async function () {
- const video = await servers[0].videos.getWithToken({ token: userAccessToken1, id: servers[0].store.videoCreated.uuid })
- expect(video.blacklisted).to.be.true
- })
-
- it('Should succeed with an admin', async function () {
- const video = servers[0].store.videoCreated
-
- for (const id of [ video.id, video.uuid, video.shortUUID ]) {
- const video = await servers[0].videos.getWithToken({ id, expectedStatus: HttpStatusCode.OK_200 })
- expect(video.blacklisted).to.be.true
- }
- })
- })
-
- describe('When removing a video in blacklist', function () {
-
- it('Should fail with a non authenticated user', async function () {
- await command.remove({
- token: 'fake token',
- videoId: servers[0].store.videoCreated.uuid,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await command.remove({
- token: userAccessToken2,
- videoId: servers[0].store.videoCreated.uuid,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an incorrect id', async function () {
- await command.remove({ videoId: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a not blacklisted video', async function () {
- // The video was not added to the blacklist so it should fail
- await command.remove({ videoId: notBlacklistedVideoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.remove({ videoId: servers[0].store.videoCreated.uuid, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- })
- })
-
- describe('When listing videos in blacklist', function () {
- const basePath = '/api/v1/videos/blacklist/'
-
- it('Should fail with a non authenticated user', async function () {
- await servers[0].blacklist.list({ token: 'fake token', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a non admin user', async function () {
- await servers[0].blacklist.list({ token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(servers[0].url, basePath, servers[0].accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(servers[0].url, basePath, servers[0].accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(servers[0].url, basePath, servers[0].accessToken)
- })
-
- it('Should fail with an invalid type', async function () {
- await servers[0].blacklist.list({ type: 0 as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await servers[0].blacklist.list({ type: VideoBlacklistType.MANUAL })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/video-captions.ts b/server/tests/api/check-params/video-captions.ts
deleted file mode 100644
index 532dab1c4..000000000
--- a/server/tests/api/check-params/video-captions.ts
+++ /dev/null
@@ -1,307 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makeUploadRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test video captions API validator', function () {
- const path = '/api/v1/videos/'
-
- let server: PeerTubeServer
- let userAccessToken: string
- let video: VideoCreateResult
- let privateVideo: VideoCreateResult
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- video = await server.videos.upload()
- privateVideo = await server.videos.upload({ attributes: { privacy: VideoPrivacy.PRIVATE } })
-
- {
- const user = {
- username: 'user1',
- password: 'my super password'
- }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- }
- })
-
- describe('When adding video caption', function () {
- const fields = { }
- const attaches = {
- captionfile: buildAbsoluteFixturePath('subtitle-good1.vtt')
- }
-
- it('Should fail without a valid uuid', async function () {
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df563d0b06/captions/fr',
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with an unknown id', async function () {
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions/fr',
- token: server.accessToken,
- fields,
- attaches,
- expectedStatus: 404
- })
- })
-
- it('Should fail with a missing language in path', async function () {
- const captionPath = path + video.uuid + '/captions'
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: captionPath,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with an unknown language', async function () {
- const captionPath = path + video.uuid + '/captions/15'
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: captionPath,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail without access token', async function () {
- const captionPath = path + video.uuid + '/captions/fr'
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: captionPath,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad access token', async function () {
- const captionPath = path + video.uuid + '/captions/fr'
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: captionPath,
- token: 'blabla',
- fields,
- attaches,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- // We accept any file now
- // it('Should fail with an invalid captionfile extension', async function () {
- // const attaches = {
- // 'captionfile': buildAbsoluteFixturePath('subtitle-bad.txt')
- // }
- //
- // const captionPath = path + video.uuid + '/captions/fr'
- // await makeUploadRequest({
- // method: 'PUT',
- // url: server.url,
- // path: captionPath,
- // token: server.accessToken,
- // fields,
- // attaches,
- // expectedStatus: HttpStatusCode.BAD_REQUEST_400
- // })
- // })
-
- // We don't check the extension yet
- // it('Should fail with an invalid captionfile extension and octet-stream mime type', async function () {
- // await createVideoCaption({
- // url: server.url,
- // accessToken: server.accessToken,
- // language: 'zh',
- // videoId: video.uuid,
- // fixture: 'subtitle-bad.txt',
- // mimeType: 'application/octet-stream',
- // expectedStatus: HttpStatusCode.BAD_REQUEST_400
- // })
- // })
-
- it('Should succeed with a valid captionfile extension and octet-stream mime type', async function () {
- await server.captions.add({
- language: 'zh',
- videoId: video.uuid,
- fixture: 'subtitle-good.srt',
- mimeType: 'application/octet-stream'
- })
- })
-
- // We don't check the file validity yet
- // it('Should fail with an invalid captionfile srt', async function () {
- // const attaches = {
- // 'captionfile': buildAbsoluteFixturePath('subtitle-bad.srt')
- // }
- //
- // const captionPath = path + video.uuid + '/captions/fr'
- // await makeUploadRequest({
- // method: 'PUT',
- // url: server.url,
- // path: captionPath,
- // token: server.accessToken,
- // fields,
- // attaches,
- // expectedStatus: HttpStatusCode.INTERNAL_SERVER_ERROR_500
- // })
- // })
-
- it('Should success with the correct parameters', async function () {
- const captionPath = path + video.uuid + '/captions/fr'
- await makeUploadRequest({
- method: 'PUT',
- url: server.url,
- path: captionPath,
- token: server.accessToken,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When listing video captions', function () {
- it('Should fail without a valid uuid', async function () {
- await makeGetRequest({ url: server.url, path: path + '4da6fde3-88f7-4d16-b119-108df563d0b06/captions' })
- })
-
- it('Should fail with an unknown id', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a private video without token', async function () {
- await makeGetRequest({
- url: server.url,
- path: path + privateVideo.shortUUID + '/captions',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another user token', async function () {
- await makeGetRequest({
- url: server.url,
- token: userAccessToken,
- path: path + privateVideo.shortUUID + '/captions',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: path + video.shortUUID + '/captions', expectedStatus: HttpStatusCode.OK_200 })
-
- await makeGetRequest({
- url: server.url,
- path: path + privateVideo.shortUUID + '/captions',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When deleting video caption', function () {
- it('Should fail without a valid uuid', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df563d0b06/captions/fr',
- token: server.accessToken
- })
- })
-
- it('Should fail with an unknown id', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions/fr',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an invalid language', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/captions/16',
- token: server.accessToken
- })
- })
-
- it('Should fail with a missing language', async function () {
- const captionPath = path + video.shortUUID + '/captions'
- await makeDeleteRequest({ url: server.url, path: captionPath, token: server.accessToken })
- })
-
- it('Should fail with an unknown language', async function () {
- const captionPath = path + video.shortUUID + '/captions/15'
- await makeDeleteRequest({ url: server.url, path: captionPath, token: server.accessToken })
- })
-
- it('Should fail without access token', async function () {
- const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({ url: server.url, path: captionPath, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a bad access token', async function () {
- const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({ url: server.url, path: captionPath, token: 'coucou', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another user', async function () {
- const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({
- url: server.url,
- path: captionPath,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should success with the correct parameters', async function () {
- const captionPath = path + video.shortUUID + '/captions/fr'
- await makeDeleteRequest({
- url: server.url,
- path: captionPath,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
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 @@
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared'
-import { HttpStatusCode, VideoChannelSyncCreate } from '@shared/models'
-import {
- ChannelSyncsCommand,
- createSingleServer,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test video channel sync API validator', () => {
- const path = '/api/v1/video-channel-syncs'
- let server: PeerTubeServer
- let command: ChannelSyncsCommand
- let rootChannelId: number
- let rootChannelSyncId: number
- const userInfo = {
- accessToken: '',
- username: 'user1',
- id: -1,
- channelId: -1,
- syncId: -1
- }
-
- async function withChannelSyncDisabled (callback: () => Promise): Promise {
- try {
- await server.config.disableChannelSync()
- await callback()
- } finally {
- await server.config.enableChannelSync()
- }
- }
-
- async function withMaxSyncsPerUser (maxSync: number, callback: () => Promise): Promise {
- const origConfig = await server.config.getCustomConfig()
-
- await server.config.updateExistingSubConfig({
- newConfig: {
- import: {
- videoChannelSynchronization: {
- maxPerUser: maxSync
- }
- }
- }
- })
-
- try {
- await callback()
- } finally {
- await server.config.updateCustomConfig({ newCustomConfig: origConfig })
- }
- }
-
- before(async function () {
- this.timeout(30_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- command = server.channelSyncs
-
- rootChannelId = server.store.channel.id
-
- {
- userInfo.accessToken = await server.users.generateUserAndToken(userInfo.username)
-
- const { videoChannels, id: userId } = await server.users.getMyInfo({ token: userInfo.accessToken })
- userInfo.id = userId
- userInfo.channelId = videoChannels[0].id
- }
-
- await server.config.enableChannelSync()
- })
-
- describe('When creating a sync', function () {
- let baseCorrectParams: VideoChannelSyncCreate
-
- before(function () {
- baseCorrectParams = {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: rootChannelId
- }
- })
-
- it('Should fail when sync is disabled', async function () {
- await withChannelSyncDisabled(async () => {
- await command.create({
- token: server.accessToken,
- attributes: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with no authentication', async function () {
- await command.create({
- token: null,
- attributes: baseCorrectParams,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail without a target url', async function () {
- const attributes: VideoChannelSyncCreate = {
- ...baseCorrectParams,
- externalChannelUrl: null
- }
- await command.create({
- token: server.accessToken,
- attributes,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail without a channelId', async function () {
- const attributes: VideoChannelSyncCreate = {
- ...baseCorrectParams,
- videoChannelId: null
- }
- await command.create({
- token: server.accessToken,
- attributes,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a channelId refering nothing', async function () {
- const attributes: VideoChannelSyncCreate = {
- ...baseCorrectParams,
- videoChannelId: 42
- }
- await command.create({
- token: server.accessToken,
- attributes,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail to create a sync when the user does not own the channel', async function () {
- await command.create({
- token: userInfo.accessToken,
- attributes: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed to create a sync with root and for another user\'s channel', async function () {
- const { videoChannelSync } = await command.create({
- token: server.accessToken,
- attributes: {
- ...baseCorrectParams,
- videoChannelId: userInfo.channelId
- },
- expectedStatus: HttpStatusCode.OK_200
- })
- userInfo.syncId = videoChannelSync.id
- })
-
- it('Should succeed with the correct parameters', async function () {
- const { videoChannelSync } = await command.create({
- token: server.accessToken,
- attributes: baseCorrectParams,
- expectedStatus: HttpStatusCode.OK_200
- })
- rootChannelSyncId = videoChannelSync.id
- })
-
- it('Should fail when the user exceeds allowed number of synchronizations', async function () {
- await withMaxSyncsPerUser(1, async () => {
- await command.create({
- token: server.accessToken,
- attributes: {
- ...baseCorrectParams,
- videoChannelId: userInfo.channelId
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
- })
-
- describe('When listing my channel syncs', function () {
- const myPath = '/api/v1/accounts/root/video-channel-syncs'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should succeed with the correct parameters', async function () {
- await command.listByAccount({
- accountName: 'root',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should fail with no authentication', async function () {
- await command.listByAccount({
- accountName: 'root',
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail when a simple user lists another user\'s synchronizations', async function () {
- await command.listByAccount({
- accountName: 'root',
- token: userInfo.accessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed when root lists another user\'s synchronizations', async function () {
- await command.listByAccount({
- accountName: userInfo.username,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should succeed even with synchronization disabled', async function () {
- await withChannelSyncDisabled(async function () {
- await command.listByAccount({
- accountName: 'root',
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
- })
-
- describe('When triggering deletion', function () {
- it('should fail with no authentication', async function () {
- await command.delete({
- channelSyncId: userInfo.syncId,
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail when channelSyncId does not refer to any sync', async function () {
- await command.delete({
- channelSyncId: 42,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail when sync is not owned by the user', async function () {
- await command.delete({
- channelSyncId: rootChannelSyncId,
- token: userInfo.accessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed when root delete a sync they do not own', async function () {
- await command.delete({
- channelSyncId: userInfo.syncId,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('should succeed when user delete a sync they own', async function () {
- const { videoChannelSync } = await command.create({
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: userInfo.channelId
- },
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- await command.delete({
- channelSyncId: videoChannelSync.id,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should succeed even when synchronization is disabled', async function () {
- await withChannelSyncDisabled(async function () {
- await command.delete({
- channelSyncId: rootChannelSyncId,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
- })
-
- after(async function () {
- await server?.kill()
- })
-})
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
deleted file mode 100644
index 1782474fd..000000000
--- a/server/tests/api/check-params/video-channels.ts
+++ /dev/null
@@ -1,378 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { buildAbsoluteFixturePath, omit } from '@shared/core-utils'
-import { HttpStatusCode, VideoChannelUpdate } from '@shared/models'
-import {
- ChannelsCommand,
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- makeUploadRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test video channels API validator', function () {
- const videoChannelPath = '/api/v1/video-channels'
- let server: PeerTubeServer
- const userInfo = {
- accessToken: '',
- channelName: 'fake_channel',
- id: -1,
- videoQuota: -1,
- videoQuotaDaily: -1
- }
- let command: ChannelsCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const userCreds = {
- username: 'fake',
- password: 'fake_password'
- }
-
- {
- const user = await server.users.create({ username: userCreds.username, password: userCreds.password })
- userInfo.id = user.id
- userInfo.accessToken = await server.login.getAccessToken(userCreds)
- }
-
- command = server.channels
- })
-
- describe('When listing a video channels', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
- })
- })
-
- describe('When listing account video channels', function () {
- const accountChannelPath = '/api/v1/accounts/fake/video-channels'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, accountChannelPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, accountChannelPath, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, accountChannelPath, server.accessToken)
- })
-
- it('Should fail with a unknown account', async function () {
- await server.channels.listByAccount({ accountName: 'unknown', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path: accountChannelPath,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When adding a video channel', function () {
- const baseCorrectParams = {
- name: 'super_channel',
- displayName: 'hello',
- description: 'super description',
- support: 'super support text'
- }
-
- it('Should fail with a non authenticated user', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: videoChannelPath,
- token: 'none',
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail without a name', async function () {
- const fields = omit(baseCorrectParams, [ 'name' ])
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad name', async function () {
- const fields = { ...baseCorrectParams, name: 'super name' }
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail without a name', async function () {
- const fields = omit(baseCorrectParams, [ 'displayName' ])
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, displayName: 'super'.repeat(25) }
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(201) }
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
- await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: videoChannelPath,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should fail when adding a channel with the same username', async function () {
- await makePostBodyRequest({
- url: server.url,
- path: videoChannelPath,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
- })
-
- describe('When updating a video channel', function () {
- const baseCorrectParams: VideoChannelUpdate = {
- displayName: 'hello',
- description: 'super description',
- support: 'toto',
- bulkVideosSupportUpdate: false
- }
- let path: string
-
- before(async function () {
- path = videoChannelPath + '/super_channel'
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: 'hi',
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another authenticated user', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: userInfo.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, displayName: 'super'.repeat(25) }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(201) }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad bulkVideosSupportUpdate field', async function () {
- const fields = { ...baseCorrectParams, bulkVideosSupportUpdate: 'super' }
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makePutBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When updating video channel avatars/banners', function () {
- const types = [ 'avatar', 'banner' ]
- let path: string
-
- before(async function () {
- path = videoChannelPath + '/super_channel'
- })
-
- it('Should fail with an incorrect input file', async function () {
- for (const type of types) {
- const fields = {}
- const attaches = {
- [type + 'file']: buildAbsoluteFixturePath('video_short.mp4')
- }
-
- await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches })
- }
- })
-
- it('Should fail with a big file', async function () {
- for (const type of types) {
- const fields = {}
- const attaches = {
- [type + 'file']: buildAbsoluteFixturePath('avatar-big.png')
- }
- await makeUploadRequest({ url: server.url, path: `${path}/${type}/pick`, token: server.accessToken, fields, attaches })
- }
- })
-
- it('Should fail with an unauthenticated user', async function () {
- for (const type of types) {
- const fields = {}
- const attaches = {
- [type + 'file']: buildAbsoluteFixturePath('avatar.png')
- }
- await makeUploadRequest({
- url: server.url,
- path: `${path}/${type}/pick`,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- }
- })
-
- it('Should succeed with the correct params', async function () {
- for (const type of types) {
- const fields = {}
- const attaches = {
- [type + 'file']: buildAbsoluteFixturePath('avatar.png')
- }
- await makeUploadRequest({
- url: server.url,
- path: `${path}/${type}/pick`,
- token: server.accessToken,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- })
- })
-
- describe('When getting a video channel', function () {
- it('Should return the list of the video channels with nothing', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: videoChannelPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.data).to.be.an('array')
- })
-
- it('Should return 404 with an incorrect video channel', async function () {
- await makeGetRequest({
- url: server.url,
- path: videoChannelPath + '/super_channel2',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeGetRequest({
- url: server.url,
- path: videoChannelPath + '/super_channel',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When getting channel followers', function () {
- const path = '/api/v1/video-channels/super_channel/followers'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a another user', async function () {
- await makeGetRequest({ url: server.url, path, token: userInfo.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When deleting a video channel', function () {
- it('Should fail with a non authenticated user', async function () {
- await command.delete({ token: 'coucou', channelName: 'super_channel', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another authenticated user', async function () {
- await command.delete({ token: userInfo.accessToken, channelName: 'super_channel', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with an unknown video channel id', async function () {
- await command.delete({ channelName: 'super_channel2', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await command.delete({ channelName: 'super_channel' })
- })
-
- it('Should fail to delete the last user video channel', async function () {
- await command.delete({ channelName: 'root_channel', expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts
deleted file mode 100644
index 9f497c0cf..000000000
--- a/server/tests/api/check-params/video-comments.ts
+++ /dev/null
@@ -1,484 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test video comments API validator', function () {
- let pathThread: string
- let pathComment: string
-
- let server: PeerTubeServer
-
- let video: VideoCreateResult
-
- let userAccessToken: string
- let userAccessToken2: string
-
- let commentId: number
- let privateCommentId: number
- let privateVideo: VideoCreateResult
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- {
- video = await server.videos.upload({ attributes: {} })
- pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
- }
-
- {
- privateVideo = await server.videos.upload({ attributes: { privacy: VideoPrivacy.PRIVATE } })
- }
-
- {
- const created = await server.comments.createThread({ videoId: video.uuid, text: 'coucou' })
- commentId = created.id
- pathComment = '/api/v1/videos/' + video.uuid + '/comments/' + commentId
- }
-
- {
- const created = await server.comments.createThread({ videoId: privateVideo.uuid, text: 'coucou' })
- privateCommentId = created.id
- }
-
- {
- const user = { username: 'user1', password: 'my super password' }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
- }
-
- {
- const user = { username: 'user2', password: 'my super password' }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken2 = await server.login.getAccessToken(user)
- }
- })
-
- describe('When listing video comment threads', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, pathThread, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, pathThread, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, pathThread, server.accessToken)
- })
-
- it('Should fail with an incorrect video', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a private video without token', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another user token', async function () {
- await makeGetRequest({
- url: server.url,
- token: userAccessToken,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When listing comments of a thread', function () {
- it('Should fail with an incorrect video', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads/' + commentId,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an incorrect thread id', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/156',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a private video without token', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another user token', async function () {
- await makeGetRequest({
- url: server.url,
- token: userAccessToken,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should success with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads/' + privateCommentId,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- await makeGetRequest({
- url: server.url,
- path: '/api/v1/videos/' + video.shortUUID + '/comment-threads/' + commentId,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When adding a video thread', function () {
-
- it('Should fail with a non authenticated user', async function () {
- const fields = {
- text: 'text'
- }
- await makePostBodyRequest({
- url: server.url,
- path: pathThread,
- token: 'none',
- fields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
- })
-
- it('Should fail with a short comment', async function () {
- const fields = {
- text: ''
- }
- await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
- })
-
- it('Should fail with a long comment', async function () {
- const fields = {
- text: 'h'.repeat(10001)
- }
- await makePostBodyRequest({ url: server.url, path: pathThread, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect video', async function () {
- const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comment-threads'
- const fields = { text: 'super comment' }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a private video of another user', async function () {
- const fields = { text: 'super comment' }
-
- await makePostBodyRequest({
- url: server.url,
- path: '/api/v1/videos/' + privateVideo.shortUUID + '/comment-threads',
- token: userAccessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- const fields = { text: 'super comment' }
-
- await makePostBodyRequest({
- url: server.url,
- path: pathThread,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When adding a comment to a thread', function () {
-
- it('Should fail with a non authenticated user', async function () {
- const fields = {
- text: 'text'
- }
- await makePostBodyRequest({
- url: server.url,
- path: pathComment,
- token: 'none',
- fields,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
- })
-
- it('Should fail with a short comment', async function () {
- const fields = {
- text: ''
- }
- await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
- })
-
- it('Should fail with a long comment', async function () {
- const fields = {
- text: 'h'.repeat(10001)
- }
- await makePostBodyRequest({ url: server.url, path: pathComment, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect video', async function () {
- const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comments/' + commentId
- const fields = {
- text: 'super comment'
- }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a private video of another user', async function () {
- const fields = { text: 'super comment' }
-
- await makePostBodyRequest({
- url: server.url,
- path: '/api/v1/videos/' + privateVideo.uuid + '/comments/' + privateCommentId,
- token: userAccessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an incorrect comment', async function () {
- const path = '/api/v1/videos/' + video.uuid + '/comments/124'
- const fields = {
- text: 'super comment'
- }
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- const fields = {
- text: 'super comment'
- }
- await makePostBodyRequest({
- url: server.url,
- path: pathComment,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When removing video comments', function () {
- it('Should fail with a non authenticated user', async function () {
- await makeDeleteRequest({ url: server.url, path: pathComment, token: 'none', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another user', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: pathComment,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an incorrect video', async function () {
- const path = '/api/v1/videos/ba708d62-e3d7-45d9-9d73-41b9097cc02d/comments/' + commentId
- await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an incorrect comment', async function () {
- const path = '/api/v1/videos/' + video.uuid + '/comments/124'
- await makeDeleteRequest({ url: server.url, path, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with the same user', async function () {
- let commentToDelete: number
-
- {
- const created = await server.comments.createThread({ videoId: video.uuid, token: userAccessToken, text: 'hello' })
- commentToDelete = created.id
- }
-
- const path = '/api/v1/videos/' + video.uuid + '/comments/' + commentToDelete
-
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- })
-
- it('Should succeed with the owner of the video', async function () {
- let commentToDelete: number
- let anotherVideoUUID: string
-
- {
- const { uuid } = await server.videos.upload({ token: userAccessToken, attributes: { name: 'video' } })
- anotherVideoUUID = uuid
- }
-
- {
- const created = await server.comments.createThread({ videoId: anotherVideoUUID, text: 'hello' })
- commentToDelete = created.id
- }
-
- const path = '/api/v1/videos/' + anotherVideoUUID + '/comments/' + commentToDelete
-
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken2, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeDeleteRequest({ url: server.url, path, token: userAccessToken, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeDeleteRequest({
- url: server.url,
- path: pathComment,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When a video has comments disabled', function () {
- before(async function () {
- video = await server.videos.upload({ attributes: { commentsEnabled: false } })
- pathThread = '/api/v1/videos/' + video.uuid + '/comment-threads'
- })
-
- it('Should return an empty thread list', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: pathThread,
- expectedStatus: HttpStatusCode.OK_200
- })
- expect(res.body.total).to.equal(0)
- expect(res.body.data).to.have.lengthOf(0)
- })
-
- it('Should return an thread comments list')
-
- it('Should return conflict on thread add', async function () {
- const fields = {
- text: 'super comment'
- }
- await makePostBodyRequest({
- url: server.url,
- path: pathThread,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should return conflict on comment thread add')
- })
-
- describe('When listing admin comments threads', function () {
- const path = '/api/v1/videos/comments'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a non authenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a non admin user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- token: server.accessToken,
- query: {
- isLocal: false,
- search: 'toto',
- searchAccount: 'toto',
- searchVideo: 'toto'
- },
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-files.ts b/server/tests/api/check-params/video-files.ts
deleted file mode 100644
index 01d6a912b..000000000
--- a/server/tests/api/check-params/video-files.ts
+++ /dev/null
@@ -1,195 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { getAllFiles } from '@shared/core-utils'
-import { HttpStatusCode, UserRole, VideoDetails, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeRawRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test videos files', function () {
- let servers: PeerTubeServer[]
-
- let userToken: string
- let moderatorToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(300_000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- userToken = await servers[0].users.generateUserAndToken('user', UserRole.USER)
- moderatorToken = await servers[0].users.generateUserAndToken('moderator', UserRole.MODERATOR)
- })
-
- describe('Getting metadata', function () {
- let video: VideoDetails
-
- before(async function () {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- video = await servers[0].videos.getWithToken({ id: uuid })
- })
-
- it('Should not get metadata of private video without token', async function () {
- for (const file of getAllFiles(video)) {
- await makeRawRequest({ url: file.metadataUrl, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- }
- })
-
- it('Should not get metadata of private video without the appropriate token', async function () {
- for (const file of getAllFiles(video)) {
- await makeRawRequest({ url: file.metadataUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- }
- })
-
- it('Should get metadata of private video with the appropriate token', async function () {
- for (const file of getAllFiles(video)) {
- await makeRawRequest({ url: file.metadataUrl, token: servers[0].accessToken, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
- })
-
- describe('Deleting files', function () {
- let webVideoId: string
- let hlsId: string
- let remoteId: string
-
- let validId1: string
- let validId2: string
-
- let hlsFileId: number
- let webVideoFileId: number
-
- let remoteHLSFileId: number
- let remoteWebVideoFileId: number
-
- before(async function () {
- this.timeout(300_000)
-
- {
- const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' })
- await waitJobs(servers)
-
- const video = await servers[1].videos.get({ id: uuid })
- remoteId = video.uuid
- remoteHLSFileId = video.streamingPlaylists[0].files[0].id
- remoteWebVideoFileId = video.files[0].id
- }
-
- {
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'both 1' })
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
- validId1 = video.uuid
- hlsFileId = video.streamingPlaylists[0].files[0].id
- webVideoFileId = video.files[0].id
- }
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'both 2' })
- validId2 = uuid
- }
- }
-
- await waitJobs(servers)
-
- {
- await servers[0].config.enableTranscoding({ hls: true, webVideo: false })
- const { uuid } = await servers[0].videos.quickUpload({ name: 'hls' })
- hlsId = uuid
- }
-
- await waitJobs(servers)
-
- {
- await servers[0].config.enableTranscoding({ webVideo: true, hls: false })
- const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
- webVideoId = uuid
- }
-
- await waitJobs(servers)
- })
-
- it('Should not delete files of a unknown video', async function () {
- const expectedStatus = HttpStatusCode.NOT_FOUND_404
-
- await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: 404, expectedStatus })
-
- await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus })
- await servers[0].videos.removeWebVideoFile({ videoId: 404, fileId: webVideoFileId, expectedStatus })
- })
-
- it('Should not delete unknown files', async function () {
- const expectedStatus = HttpStatusCode.NOT_FOUND_404
-
- await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webVideoFileId, expectedStatus })
- await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: hlsFileId, expectedStatus })
- })
-
- it('Should not delete files of a remote video', async function () {
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
-
- await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: remoteId, expectedStatus })
-
- await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus })
- await servers[0].videos.removeWebVideoFile({ videoId: remoteId, fileId: remoteWebVideoFileId, expectedStatus })
- })
-
- it('Should not delete files by a non admin user', async function () {
- const expectedStatus = HttpStatusCode.FORBIDDEN_403
-
- await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus })
- await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus })
-
- await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: userToken, expectedStatus })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: moderatorToken, expectedStatus })
-
- await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus })
- await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus })
-
- await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: userToken, expectedStatus })
- await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: moderatorToken, expectedStatus })
- })
-
- it('Should not delete files if the files are not available', async function () {
- await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should not delete files if no both versions are available', async function () {
- await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should delete files if both versions are available', async function () {
- await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId })
- await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId })
-
- await servers[0].videos.removeHLSPlaylist({ videoId: validId1 })
- await servers[0].videos.removeAllWebVideoFiles({ videoId: validId2 })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts
deleted file mode 100644
index 8c6f43c12..000000000
--- a/server/tests/api/check-params/video-imports.ts
+++ /dev/null
@@ -1,431 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared'
-import { buildAbsoluteFixturePath, omit } from '@shared/core-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- makeUploadRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video imports API validator', function () {
- const path = '/api/v1/videos/imports'
- let server: PeerTubeServer
- let userAccessToken = ''
- let channelId: number
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- const username = 'user1'
- const password = 'my super password'
- await server.users.create({ username, password })
- userAccessToken = await server.login.getAccessToken({ username, password })
-
- {
- const { videoChannels } = await server.users.getMyInfo()
- channelId = videoChannels[0].id
- }
- })
-
- describe('When listing my video imports', function () {
- const myPath = '/api/v1/users/me/videos/imports'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, myPath, server.accessToken)
- })
-
- it('Should fail with a bad videoChannelSyncId param', async function () {
- await makeGetRequest({
- url: server.url,
- path: myPath,
- query: { videoChannelSyncId: 'toto' },
- token: server.accessToken
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: myPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
- })
- })
-
- describe('When adding a video import', function () {
- let baseCorrectParams
-
- before(function () {
- baseCorrectParams = {
- targetUrl: FIXTURE_URLS.goodVideo,
- name: 'my super name',
- category: 5,
- licence: 1,
- language: 'pt',
- nsfw: false,
- commentsEnabled: true,
- downloadEnabled: true,
- waitTranscoding: true,
- description: 'my super description',
- support: 'my super support text',
- tags: [ 'tag1', 'tag2' ],
- privacy: VideoPrivacy.PUBLIC,
- channelId
- }
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail without a target url', async function () {
- const fields = omit(baseCorrectParams, [ 'targetUrl' ])
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad target url', async function () {
- const fields = { ...baseCorrectParams, targetUrl: 'htt://hello' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with localhost', async function () {
- const fields = { ...baseCorrectParams, targetUrl: 'http://localhost:8000' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a private IP target urls', async function () {
- const targetUrls = [
- 'http://127.0.0.1:8000',
- 'http://127.0.0.1',
- 'http://127.0.0.1/hello',
- 'https://192.168.1.42',
- 'http://192.168.1.42',
- 'http://127.0.0.1.cpy.re'
- ]
-
- for (const targetUrl of targetUrls) {
- const fields = { ...baseCorrectParams, targetUrl }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad category', async function () {
- const fields = { ...baseCorrectParams, category: 125 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad licence', async function () {
- const fields = { ...baseCorrectParams, licence: 125 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad language', async function () {
- const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail without a channel', async function () {
- const fields = omit(baseCorrectParams, [ 'channelId' ])
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad channel', async function () {
- const fields = { ...baseCorrectParams, channelId: 545454 }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with another user channel', async function () {
- const user = {
- username: 'fake',
- password: 'fake_password'
- }
- await server.users.create({ username: user.username, password: user.password })
-
- const accessTokenUser = await server.login.getAccessToken(user)
- const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
- const customChannelId = videoChannels[0].id
-
- const fields = { ...baseCorrectParams, channelId: customChannelId }
-
- await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
- })
-
- it('Should fail with too many tags', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too low', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too big', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: buildAbsoluteFixturePath('video_short.mp4')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with a big thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: buildAbsoluteFixturePath('custom-preview-big.png')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with an incorrect preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: buildAbsoluteFixturePath('video_short.mp4')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with a big preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: buildAbsoluteFixturePath('custom-preview-big.png')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with an invalid torrent file', async function () {
- const fields = omit(baseCorrectParams, [ 'targetUrl' ])
- const attaches = {
- torrentfile: buildAbsoluteFixturePath('avatar-big.png')
- }
-
- await makeUploadRequest({ url: server.url, path, token: server.accessToken, fields, attaches })
- })
-
- it('Should fail with an invalid magnet URI', async function () {
- let fields = omit(baseCorrectParams, [ 'targetUrl' ])
- fields = { ...fields, magnetUri: 'blabla' }
-
- await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should succeed with the correct parameters', async function () {
- this.timeout(120000)
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should forbid to import http videos', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- import: {
- videos: {
- http: {
- enabled: false
- },
- torrent: {
- enabled: true
- }
- }
- }
- }
- })
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields: baseCorrectParams,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
-
- it('Should forbid to import torrent videos', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- import: {
- videos: {
- http: {
- enabled: true
- },
- torrent: {
- enabled: false
- }
- }
- }
- }
- })
-
- let fields = omit(baseCorrectParams, [ 'targetUrl' ])
- fields = { ...fields, magnetUri: FIXTURE_URLS.magnet }
-
- await makePostBodyRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
-
- fields = omit(fields, [ 'magnetUri' ])
- const attaches = {
- torrentfile: buildAbsoluteFixturePath('video-720p.torrent')
- }
-
- await makeUploadRequest({
- url: server.url,
- path,
- token: server.accessToken,
- fields,
- attaches,
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
- })
- })
-
- describe('Deleting/cancelling a video import', function () {
- let importId: number
-
- async function importVideo () {
- const attributes = { channelId: server.store.channel.id, targetUrl: FIXTURE_URLS.goodVideo }
- const res = await server.imports.importVideo({ attributes })
-
- return res.id
- }
-
- before(async function () {
- importId = await importVideo()
- })
-
- it('Should fail with an invalid import id', async function () {
- await server.imports.cancel({ importId: 'artyom' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.imports.delete({ importId: 'artyom' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown import id', async function () {
- await server.imports.cancel({ importId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await server.imports.delete({ importId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail without token', async function () {
- await server.imports.cancel({ importId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await server.imports.delete({ importId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another user token', async function () {
- await server.imports.cancel({ importId, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await server.imports.delete({ importId, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail to cancel non pending import', async function () {
- this.timeout(60000)
-
- await waitJobs([ server ])
-
- await server.imports.cancel({ importId, expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should succeed to delete an import', async function () {
- await server.imports.delete({ importId })
- })
-
- it('Should fail to delete a pending import', async function () {
- await server.jobs.pauseJobQueue()
-
- importId = await importVideo()
-
- await server.imports.delete({ importId, expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should succeed to cancel an import', async function () {
- importId = await importVideo()
-
- await server.imports.cancel({ importId })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-passwords.ts b/server/tests/api/check-params/video-passwords.ts
deleted file mode 100644
index 50b0bacb3..000000000
--- a/server/tests/api/check-params/video-passwords.ts
+++ /dev/null
@@ -1,609 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import {
- FIXTURE_URLS,
- checkBadCountPagination,
- checkBadSortPagination,
- checkBadStartPagination,
- checkUploadVideoParam
-} from '@server/tests/shared'
-import { root } from '@shared/core-utils'
-import {
- HttpStatusCode,
- PeerTubeProblemDocument,
- ServerErrorCode,
- VideoCreateResult,
- VideoPrivacy
-} from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makePostBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { expect } from 'chai'
-import { join } from 'path'
-
-describe('Test video passwords validator', function () {
- let path: string
- let server: PeerTubeServer
- let userAccessToken = ''
- let video: VideoCreateResult
- let channelId: number
- let publicVideo: VideoCreateResult
- let commentId: number
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(50000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- latencySetting: {
- enabled: false
- },
- allowReplay: false
- },
- import: {
- videos: {
- http:{
- enabled: true
- }
- }
- }
- }
- })
-
- userAccessToken = await server.users.generateUserAndToken('user1')
-
- {
- const body = await server.users.getMyInfo()
- channelId = body.videoChannels[0].id
- }
-
- {
- video = await server.videos.quickUpload({
- name: 'password protected video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ 'password1', 'password2' ]
- })
- }
- path = '/api/v1/videos/'
- })
-
- async function checkVideoPasswordOptions (options: {
- server: PeerTubeServer
- token: string
- videoPasswords: string[]
- expectedStatus: HttpStatusCode
- mode: 'uploadLegacy' | 'uploadResumable' | 'import' | 'updateVideo' | 'updatePasswords' | 'live'
- }) {
- const { server, token, videoPasswords, expectedStatus = HttpStatusCode.OK_200, mode } = options
- const attaches = {
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.webm')
- }
- const baseCorrectParams = {
- name: 'my super name',
- category: 5,
- licence: 1,
- language: 'pt',
- nsfw: false,
- commentsEnabled: true,
- downloadEnabled: true,
- waitTranscoding: true,
- description: 'my super description',
- support: 'my super support text',
- tags: [ 'tag1', 'tag2' ],
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- channelId,
- originallyPublishedAt: new Date().toISOString()
- }
- if (mode === 'uploadLegacy') {
- const fields = { ...baseCorrectParams, videoPasswords }
- return checkUploadVideoParam({ server, token, attributes: { ...fields, ...attaches }, expectedStatus, mode: 'legacy' })
- }
-
- if (mode === 'uploadResumable') {
- const fields = { ...baseCorrectParams, videoPasswords }
- return checkUploadVideoParam({ server, token, attributes: { ...fields, ...attaches }, expectedStatus, mode: 'resumable' })
- }
-
- if (mode === 'import') {
- const attributes = { ...baseCorrectParams, targetUrl: FIXTURE_URLS.goodVideo, videoPasswords }
- return server.imports.importVideo({ attributes, expectedStatus })
- }
-
- if (mode === 'updateVideo') {
- const attributes = { ...baseCorrectParams, videoPasswords }
- return server.videos.update({ token, expectedStatus, id: video.id, attributes })
- }
-
- if (mode === 'updatePasswords') {
- return server.videoPasswords.updateAll({ token, expectedStatus, videoId: video.id, passwords: videoPasswords })
- }
-
- if (mode === 'live') {
- const fields = { ...baseCorrectParams, videoPasswords }
-
- return server.live.create({ fields, expectedStatus })
- }
- }
-
- function validateVideoPasswordList (mode: 'uploadLegacy' | 'uploadResumable' | 'import' | 'updateVideo' | 'updatePasswords' | 'live') {
-
- it('Should fail with a password protected privacy without providing a password', async function () {
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords: undefined,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- it('Should fail with a password protected privacy and an empty password list', async function () {
- const videoPasswords = []
-
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- it('Should fail with a password protected privacy and a too short password', async function () {
- const videoPasswords = [ 'p' ]
-
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- it('Should fail with a password protected privacy and a too long password', async function () {
- const videoPasswords = [ 'Very very very very very very very very very very very very very very very very very very long password' ]
-
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- it('Should fail with a password protected privacy and an empty password', async function () {
- const videoPasswords = [ '' ]
-
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- it('Should fail with a password protected privacy and duplicated passwords', async function () {
- const videoPasswords = [ 'password', 'password' ]
-
- await checkVideoPasswordOptions({
- server,
- token: server.accessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- })
- })
-
- if (mode === 'updatePasswords') {
- it('Should fail for an unauthenticated user', async function () {
- const videoPasswords = [ 'password' ]
- await checkVideoPasswordOptions({
- server,
- token: null,
- videoPasswords,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401,
- mode
- })
- })
-
- it('Should fail for an unauthorized user', async function () {
- const videoPasswords = [ 'password' ]
- await checkVideoPasswordOptions({
- server,
- token: userAccessToken,
- videoPasswords,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- mode
- })
- })
- }
-
- it('Should succeed with a password protected privacy and correct passwords', async function () {
- const videoPasswords = [ 'password1', 'password2' ]
- const expectedStatus = mode === 'updatePasswords' || mode === 'updateVideo'
- ? HttpStatusCode.NO_CONTENT_204
- : HttpStatusCode.OK_200
-
- await checkVideoPasswordOptions({ server, token: server.accessToken, videoPasswords, expectedStatus, mode })
- })
- }
-
- describe('When adding or updating a video', function () {
- describe('Resumable upload', function () {
- validateVideoPasswordList('uploadResumable')
- })
-
- describe('Legacy upload', function () {
- validateVideoPasswordList('uploadLegacy')
- })
-
- describe('When importing a video', function () {
- validateVideoPasswordList('import')
- })
-
- describe('When updating a video', function () {
- validateVideoPasswordList('updateVideo')
- })
-
- describe('When updating the password list of a video', function () {
- validateVideoPasswordList('updatePasswords')
- })
-
- describe('When creating a live', function () {
- validateVideoPasswordList('live')
- })
- })
-
- async function checkVideoAccessOptions (options: {
- server: PeerTubeServer
- token?: string
- videoPassword?: string
- expectedStatus: HttpStatusCode
- mode: 'get' | 'getWithPassword' | 'getWithToken' | 'listCaptions' | 'createThread' | 'listThreads' | 'replyThread' | 'rate' | 'token'
- }) {
- const { server, token = null, videoPassword, expectedStatus, mode } = options
-
- if (mode === 'get') {
- return server.videos.get({ id: video.id, expectedStatus })
- }
-
- if (mode === 'getWithToken') {
- return server.videos.getWithToken({
- id: video.id,
- token,
- expectedStatus
- })
- }
-
- if (mode === 'getWithPassword') {
- return server.videos.getWithPassword({
- id: video.id,
- token,
- expectedStatus,
- password: videoPassword
- })
- }
-
- if (mode === 'rate') {
- return server.videos.rate({
- id: video.id,
- token,
- expectedStatus,
- rating: 'like',
- videoPassword
- })
- }
-
- if (mode === 'createThread') {
- const fields = { text: 'super comment' }
- const headers = videoPassword !== undefined && videoPassword !== null
- ? { 'x-peertube-video-password': videoPassword }
- : undefined
- const body = await makePostBodyRequest({
- url: server.url,
- path: path + video.uuid + '/comment-threads',
- token,
- fields,
- headers,
- expectedStatus
- })
- return JSON.parse(body.text)
- }
-
- if (mode === 'replyThread') {
- const fields = { text: 'super reply' }
- const headers = videoPassword !== undefined && videoPassword !== null
- ? { 'x-peertube-video-password': videoPassword }
- : undefined
- return makePostBodyRequest({
- url: server.url,
- path: path + video.uuid + '/comments/' + commentId,
- token,
- fields,
- headers,
- expectedStatus
- })
- }
- if (mode === 'listThreads') {
- return server.comments.listThreads({
- videoId: video.id,
- token,
- expectedStatus,
- videoPassword
- })
- }
-
- if (mode === 'listCaptions') {
- return server.captions.list({
- videoId: video.id,
- token,
- expectedStatus,
- videoPassword
- })
- }
-
- if (mode === 'token') {
- return server.videoToken.create({
- videoId: video.id,
- token,
- expectedStatus,
- videoPassword
- })
- }
- }
-
- function checkVideoError (error: any, mode: 'providePassword' | 'incorrectPassword') {
- const serverCode = mode === 'providePassword'
- ? ServerErrorCode.VIDEO_REQUIRES_PASSWORD
- : ServerErrorCode.INCORRECT_VIDEO_PASSWORD
-
- const message = mode === 'providePassword'
- ? 'Please provide a password to access this password protected video'
- : 'Incorrect video password. Access to the video is denied.'
-
- if (!error.code) {
- error = JSON.parse(error.text)
- }
-
- expect(error.code).to.equal(serverCode)
- expect(error.detail).to.equal(message)
- expect(error.error).to.equal(message)
-
- expect(error.status).to.equal(HttpStatusCode.FORBIDDEN_403)
- }
-
- function validateVideoAccess (mode: 'get' | 'listCaptions' | 'createThread' | 'listThreads' | 'replyThread' | 'rate' | 'token') {
- const requiresUserAuth = [ 'createThread', 'replyThread', 'rate' ].includes(mode)
- let tokens: string[]
- if (!requiresUserAuth) {
- it('Should fail without providing a password for an unlogged user', async function () {
- const body = await checkVideoAccessOptions({ server, expectedStatus: HttpStatusCode.FORBIDDEN_403, mode })
- const error = body as unknown as PeerTubeProblemDocument
-
- checkVideoError(error, 'providePassword')
- })
- }
-
- it('Should fail without providing a password for an unauthorised user', async function () {
- const tmp = mode === 'get' ? 'getWithToken' : mode
-
- const body = await checkVideoAccessOptions({
- server,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- mode: tmp
- })
-
- const error = body as unknown as PeerTubeProblemDocument
-
- checkVideoError(error, 'providePassword')
- })
-
- it('Should fail if a wrong password is entered', async function () {
- const tmp = mode === 'get' ? 'getWithPassword' : mode
- tokens = [ userAccessToken, server.accessToken ]
-
- if (!requiresUserAuth) tokens.push(null)
-
- for (const token of tokens) {
- const body = await checkVideoAccessOptions({
- server,
- token,
- videoPassword: 'toto',
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- mode: tmp
- })
- const error = body as unknown as PeerTubeProblemDocument
-
- checkVideoError(error, 'incorrectPassword')
- }
- })
-
- it('Should fail if an empty password is entered', async function () {
- const tmp = mode === 'get' ? 'getWithPassword' : mode
-
- for (const token of tokens) {
- const body = await checkVideoAccessOptions({
- server,
- token,
- videoPassword: '',
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- mode: tmp
- })
- const error = body as unknown as PeerTubeProblemDocument
-
- checkVideoError(error, 'incorrectPassword')
- }
- })
-
- it('Should fail if an inccorect password containing the correct password is entered', async function () {
- const tmp = mode === 'get' ? 'getWithPassword' : mode
-
- for (const token of tokens) {
- const body = await checkVideoAccessOptions({
- server,
- token,
- videoPassword: 'password11',
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- mode: tmp
- })
- const error = body as unknown as PeerTubeProblemDocument
-
- checkVideoError(error, 'incorrectPassword')
- }
- })
-
- it('Should succeed without providing a password for an authorised user', async function () {
- const tmp = mode === 'get' ? 'getWithToken' : mode
- const expectedStatus = mode === 'rate' ? HttpStatusCode.NO_CONTENT_204 : HttpStatusCode.OK_200
-
- const body = await checkVideoAccessOptions({ server, token: server.accessToken, expectedStatus, mode: tmp })
-
- if (mode === 'createThread') commentId = body.comment.id
- })
-
- it('Should succeed using correct passwords', async function () {
- const tmp = mode === 'get' ? 'getWithPassword' : mode
- const expectedStatus = mode === 'rate' ? HttpStatusCode.NO_CONTENT_204 : HttpStatusCode.OK_200
-
- for (const token of tokens) {
- await checkVideoAccessOptions({ server, videoPassword: 'password1', token, expectedStatus, mode: tmp })
- await checkVideoAccessOptions({ server, videoPassword: 'password2', token, expectedStatus, mode: tmp })
- }
- })
- }
-
- describe('When accessing password protected video', function () {
-
- describe('For getting a password protected video', function () {
- validateVideoAccess('get')
- })
-
- describe('For rating a video', function () {
- validateVideoAccess('rate')
- })
-
- describe('For creating a thread', function () {
- validateVideoAccess('createThread')
- })
-
- describe('For replying to a thread', function () {
- validateVideoAccess('replyThread')
- })
-
- describe('For listing threads', function () {
- validateVideoAccess('listThreads')
- })
-
- describe('For getting captions', function () {
- validateVideoAccess('listCaptions')
- })
-
- describe('For creating video file token', function () {
- validateVideoAccess('token')
- })
- })
-
- describe('When listing passwords', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path + video.uuid + '/passwords', server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path + video.uuid + '/passwords', server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path + video.uuid + '/passwords', server.accessToken)
- })
-
- it('Should fail for unauthenticated user', async function () {
- await server.videoPasswords.list({
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401,
- videoId: video.id
- })
- })
-
- it('Should fail for unauthorized user', async function () {
- await server.videoPasswords.list({
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- videoId: video.id
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await server.videoPasswords.list({
- token: server.accessToken,
- expectedStatus: HttpStatusCode.OK_200,
- videoId: video.id
- })
- })
- })
-
- describe('When deleting a password', async function () {
- const passwords = (await server.videoPasswords.list({ videoId: video.id })).data
-
- it('Should fail with wrong password id', async function () {
- await server.videoPasswords.remove({ id: -1, videoId: video.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail for unauthenticated user', async function () {
- await server.videoPasswords.remove({
- id: passwords[0].id,
- token: null,
- videoId: video.id,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail for unauthorized user', async function () {
- await server.videoPasswords.remove({
- id: passwords[0].id,
- token: userAccessToken,
- videoId: video.id,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail for non password protected video', async function () {
- publicVideo = await server.videos.quickUpload({ name: 'public video' })
- await server.videoPasswords.remove({ id: passwords[0].id, videoId: publicVideo.id, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail for password not linked to correct video', async function () {
- const video2 = await server.videos.quickUpload({
- name: 'password protected video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ 'password1', 'password2' ]
- })
- await server.videoPasswords.remove({ id: passwords[0].id, videoId: video2.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should succeed with correct parameter', async function () {
- await server.videoPasswords.remove({ id: passwords[0].id, videoId: video.id, expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- })
-
- it('Should fail for last password of a video', async function () {
- await server.videoPasswords.remove({ id: passwords[1].id, videoId: video.id, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-playlists.ts b/server/tests/api/check-params/video-playlists.ts
deleted file mode 100644
index 8c3233e0b..000000000
--- a/server/tests/api/check-params/video-playlists.ts
+++ /dev/null
@@ -1,695 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '@server/tests/shared'
-import {
- HttpStatusCode,
- VideoPlaylistCreate,
- VideoPlaylistCreateResult,
- VideoPlaylistElementCreate,
- VideoPlaylistElementUpdate,
- VideoPlaylistPrivacy,
- VideoPlaylistReorder,
- VideoPlaylistType
-} from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- PlaylistsCommand,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test video playlists API validator', function () {
- let server: PeerTubeServer
- let userAccessToken: string
-
- let playlist: VideoPlaylistCreateResult
- let privatePlaylistUUID: string
-
- let watchLaterPlaylistId: number
- let videoId: number
- let elementId: number
-
- let command: PlaylistsCommand
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- userAccessToken = await server.users.generateUserAndToken('user1')
- videoId = (await server.videos.quickUpload({ name: 'video 1' })).id
-
- command = server.playlists
-
- {
- const { data } = await command.listByAccount({
- token: server.accessToken,
- handle: 'root',
- start: 0,
- count: 5,
- playlistType: VideoPlaylistType.WATCH_LATER
- })
- watchLaterPlaylistId = data[0].id
- }
-
- {
- playlist = await command.create({
- attributes: {
- displayName: 'super playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id
- }
- })
- }
-
- {
- const created = await command.create({
- attributes: {
- displayName: 'private',
- privacy: VideoPlaylistPrivacy.PRIVATE
- }
- })
- privatePlaylistUUID = created.uuid
- }
- })
-
- describe('When listing playlists', function () {
- const globalPath = '/api/v1/video-playlists'
- const accountPath = '/api/v1/accounts/root/video-playlists'
- const videoChannelPath = '/api/v1/video-channels/root_channel/video-playlists'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, globalPath, server.accessToken)
- await checkBadStartPagination(server.url, accountPath, server.accessToken)
- await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, globalPath, server.accessToken)
- await checkBadCountPagination(server.url, accountPath, server.accessToken)
- await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, globalPath, server.accessToken)
- await checkBadSortPagination(server.url, accountPath, server.accessToken)
- await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
- })
-
- it('Should fail with a bad playlist type', async function () {
- await makeGetRequest({ url: server.url, path: globalPath, query: { playlistType: 3 } })
- await makeGetRequest({ url: server.url, path: accountPath, query: { playlistType: 3 } })
- await makeGetRequest({ url: server.url, path: videoChannelPath, query: { playlistType: 3 } })
- })
-
- it('Should fail with a bad account parameter', async function () {
- const accountPath = '/api/v1/accounts/root2/video-playlists'
-
- await makeGetRequest({
- url: server.url,
- path: accountPath,
- expectedStatus: HttpStatusCode.NOT_FOUND_404,
- token: server.accessToken
- })
- })
-
- it('Should fail with a bad video channel parameter', async function () {
- const accountPath = '/api/v1/video-channels/bad_channel/video-playlists'
-
- await makeGetRequest({
- url: server.url,
- path: accountPath,
- expectedStatus: HttpStatusCode.NOT_FOUND_404,
- token: server.accessToken
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: globalPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
- await makeGetRequest({ url: server.url, path: accountPath, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken })
- await makeGetRequest({
- url: server.url,
- path: videoChannelPath,
- expectedStatus: HttpStatusCode.OK_200,
- token: server.accessToken
- })
- })
- })
-
- describe('When listing videos of a playlist', function () {
- const path = '/api/v1/video-playlists/'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path + playlist.shortUUID + '/videos', server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path + playlist.shortUUID + '/videos', server.accessToken)
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path: path + playlist.shortUUID + '/videos', expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When getting a video playlist', function () {
- it('Should fail with a bad id or uuid', async function () {
- await command.get({ playlistId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an unknown playlist', async function () {
- await command.get({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail to get an unlisted playlist with the number id', async function () {
- const playlist = await command.create({
- attributes: {
- displayName: 'super playlist',
- videoChannelId: server.store.channel.id,
- privacy: VideoPlaylistPrivacy.UNLISTED
- }
- })
-
- await command.get({ playlistId: playlist.id, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.get({ playlistId: playlist.uuid, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When creating/updating a video playlist', function () {
- const getBase = (
- attributes?: Partial,
- wrapper?: Partial[0]>
- ) => {
- return {
- attributes: {
- displayName: 'display name',
- privacy: VideoPlaylistPrivacy.UNLISTED,
- thumbnailfile: 'custom-thumbnail.jpg',
- videoChannelId: server.store.channel.id,
-
- ...attributes
- },
-
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
-
- ...wrapper
- }
- }
- const getUpdate = (params: any, playlistId: number | string) => {
- return { ...params, playlistId }
- }
-
- it('Should fail with an unauthenticated user', async function () {
- const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail without displayName', async function () {
- const params = getBase({ displayName: undefined })
-
- await command.create(params)
- })
-
- it('Should fail with an incorrect display name', async function () {
- const params = getBase({ displayName: 's'.repeat(300) })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail with an incorrect description', async function () {
- const params = getBase({ description: 't' })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail with an incorrect privacy', async function () {
- const params = getBase({ privacy: 45 as any })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail with an unknown video channel id', async function () {
- const params = getBase({ videoChannelId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail with an incorrect thumbnail file', async function () {
- const params = getBase({ thumbnailfile: 'video_short.mp4' })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail with a thumbnail file too big', async function () {
- const params = getBase({ thumbnailfile: 'custom-preview-big.png' })
-
- await command.create(params)
- await command.update(getUpdate(params, playlist.shortUUID))
- })
-
- it('Should fail to set "public" a playlist not assigned to a channel', async function () {
- const params = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: undefined })
- const params2 = getBase({ privacy: VideoPlaylistPrivacy.PUBLIC, videoChannelId: 'null' as any })
- const params3 = getBase({ privacy: undefined, videoChannelId: 'null' as any })
-
- await command.create(params)
- await command.create(params2)
- await command.update(getUpdate(params, privatePlaylistUUID))
- await command.update(getUpdate(params2, playlist.shortUUID))
- await command.update(getUpdate(params3, playlist.shortUUID))
- })
-
- it('Should fail with an unknown playlist to update', async function () {
- await command.update(getUpdate(
- getBase({}, { expectedStatus: HttpStatusCode.NOT_FOUND_404 }),
- 42
- ))
- })
-
- it('Should fail to update a playlist of another user', async function () {
- await command.update(getUpdate(
- getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }),
- playlist.shortUUID
- ))
- })
-
- it('Should fail to update the watch later playlist', async function () {
- await command.update(getUpdate(
- getBase({}, { expectedStatus: HttpStatusCode.BAD_REQUEST_400 }),
- watchLaterPlaylistId
- ))
- })
-
- it('Should succeed with the correct params', async function () {
- {
- const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
- await command.create(params)
- }
-
- {
- const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await command.update(getUpdate(params, playlist.shortUUID))
- }
- })
- })
-
- describe('When adding an element in a playlist', function () {
- const getBase = (
- attributes?: Partial,
- wrapper?: Partial[0]>
- ) => {
- return {
- attributes: {
- videoId,
- startTimestamp: 2,
- stopTimestamp: 3,
-
- ...attributes
- },
-
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- playlistId: playlist.id,
-
- ...wrapper
- }
- }
-
- it('Should fail with an unauthenticated user', async function () {
- const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await command.addElement(params)
- })
-
- it('Should fail with the playlist of another user', async function () {
- const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await command.addElement(params)
- })
-
- it('Should fail with an unknown or incorrect playlist id', async function () {
- {
- const params = getBase({}, { playlistId: 'toto' })
- await command.addElement(params)
- }
-
- {
- const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.addElement(params)
- }
- })
-
- it('Should fail with an unknown or incorrect video id', async function () {
- const params = getBase({ videoId: 42 }, { expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.addElement(params)
- })
-
- it('Should fail with a bad start/stop timestamp', async function () {
- {
- const params = getBase({ startTimestamp: -42 })
- await command.addElement(params)
- }
-
- {
- const params = getBase({ stopTimestamp: 'toto' as any })
- await command.addElement(params)
- }
- })
-
- it('Succeed with the correct params', async function () {
- const params = getBase({}, { expectedStatus: HttpStatusCode.OK_200 })
- const created = await command.addElement(params)
- elementId = created.id
- })
- })
-
- describe('When updating an element in a playlist', function () {
- const getBase = (
- attributes?: Partial,
- wrapper?: Partial[0]>
- ) => {
- return {
- attributes: {
- startTimestamp: 1,
- stopTimestamp: 2,
-
- ...attributes
- },
-
- elementId,
- playlistId: playlist.id,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
-
- ...wrapper
- }
- }
-
- it('Should fail with an unauthenticated user', async function () {
- const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await command.updateElement(params)
- })
-
- it('Should fail with the playlist of another user', async function () {
- const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await command.updateElement(params)
- })
-
- it('Should fail with an unknown or incorrect playlist id', async function () {
- {
- const params = getBase({}, { playlistId: 'toto' })
- await command.updateElement(params)
- }
-
- {
- const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.updateElement(params)
- }
- })
-
- it('Should fail with an unknown or incorrect playlistElement id', async function () {
- {
- const params = getBase({}, { elementId: 'toto' })
- await command.updateElement(params)
- }
-
- {
- const params = getBase({}, { elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.updateElement(params)
- }
- })
-
- it('Should fail with a bad start/stop timestamp', async function () {
- {
- const params = getBase({ startTimestamp: 'toto' as any })
- await command.updateElement(params)
- }
-
- {
- const params = getBase({ stopTimestamp: -42 })
- await command.updateElement(params)
- }
- })
-
- it('Should fail with an unknown element', async function () {
- const params = getBase({}, { elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.updateElement(params)
- })
-
- it('Succeed with the correct params', async function () {
- const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await command.updateElement(params)
- })
- })
-
- describe('When reordering elements of a playlist', function () {
- let videoId3: number
- let videoId4: number
-
- const getBase = (
- attributes?: Partial,
- wrapper?: Partial[0]>
- ) => {
- return {
- attributes: {
- startPosition: 1,
- insertAfterPosition: 2,
- reorderLength: 3,
-
- ...attributes
- },
-
- playlistId: playlist.shortUUID,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
-
- ...wrapper
- }
- }
-
- before(async function () {
- videoId3 = (await server.videos.quickUpload({ name: 'video 3' })).id
- videoId4 = (await server.videos.quickUpload({ name: 'video 4' })).id
-
- for (const id of [ videoId3, videoId4 ]) {
- await command.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: id } })
- }
- })
-
- it('Should fail with an unauthenticated user', async function () {
- const params = getBase({}, { token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await command.reorderElements(params)
- })
-
- it('Should fail with the playlist of another user', async function () {
- const params = getBase({}, { token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await command.reorderElements(params)
- })
-
- it('Should fail with an invalid playlist', async function () {
- {
- const params = getBase({}, { playlistId: 'toto' })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({}, { playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.reorderElements(params)
- }
- })
-
- it('Should fail with an invalid start position', async function () {
- {
- const params = getBase({ startPosition: -1 })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ startPosition: 'toto' as any })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ startPosition: 42 })
- await command.reorderElements(params)
- }
- })
-
- it('Should fail with an invalid insert after position', async function () {
- {
- const params = getBase({ insertAfterPosition: 'toto' as any })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ insertAfterPosition: -2 })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ insertAfterPosition: 42 })
- await command.reorderElements(params)
- }
- })
-
- it('Should fail with an invalid reorder length', async function () {
- {
- const params = getBase({ reorderLength: 'toto' as any })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ reorderLength: -2 })
- await command.reorderElements(params)
- }
-
- {
- const params = getBase({ reorderLength: 42 })
- await command.reorderElements(params)
- }
- })
-
- it('Succeed with the correct params', async function () {
- const params = getBase({}, { expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await command.reorderElements(params)
- })
- })
-
- describe('When checking exists in playlist endpoint', function () {
- const path = '/api/v1/users/me/video-playlists/videos-exist'
-
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({
- url: server.url,
- path,
- query: { videoIds: [ 1, 2 ] },
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with invalid video ids', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: { videoIds: 'toto' }
- })
-
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: { videoIds: [ 'toto' ] }
- })
-
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: { videoIds: [ 1, 'toto' ] }
- })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: { videoIds: [ 1, 2 ] },
- expectedStatus: HttpStatusCode.OK_200
- })
- })
- })
-
- describe('When deleting an element in a playlist', function () {
- const getBase = (wrapper: Partial[0]>) => {
- return {
- elementId,
- playlistId: playlist.uuid,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
-
- ...wrapper
- }
- }
-
- it('Should fail with an unauthenticated user', async function () {
- const params = getBase({ token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await command.removeElement(params)
- })
-
- it('Should fail with the playlist of another user', async function () {
- const params = getBase({ token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await command.removeElement(params)
- })
-
- it('Should fail with an unknown or incorrect playlist id', async function () {
- {
- const params = getBase({ playlistId: 'toto' })
- await command.removeElement(params)
- }
-
- {
- const params = getBase({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.removeElement(params)
- }
- })
-
- it('Should fail with an unknown or incorrect video id', async function () {
- {
- const params = getBase({ elementId: 'toto' as any })
- await command.removeElement(params)
- }
-
- {
- const params = getBase({ elementId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.removeElement(params)
- }
- })
-
- it('Should fail with an unknown element', async function () {
- const params = getBase({ elementId: 888, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await command.removeElement(params)
- })
-
- it('Succeed with the correct params', async function () {
- const params = getBase({ expectedStatus: HttpStatusCode.NO_CONTENT_204 })
- await command.removeElement(params)
- })
- })
-
- describe('When deleting a playlist', function () {
- it('Should fail with an unknown playlist', async function () {
- await command.delete({ playlistId: 42, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a playlist of another user', async function () {
- await command.delete({ token: userAccessToken, playlistId: playlist.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with the watch later playlist', async function () {
- await command.delete({ playlistId: watchLaterPlaylistId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct params', async function () {
- await command.delete({ playlistId: playlist.uuid })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-source.ts b/server/tests/api/check-params/video-source.ts
deleted file mode 100644
index 767590d5e..000000000
--- a/server/tests/api/check-params/video-source.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video sources API validator', function () {
- let server: PeerTubeServer = null
- let uuid: string
- let userToken: string
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- userToken = await server.users.generateUserAndToken('user1')
- })
-
- describe('When getting latest source', function () {
-
- before(async function () {
- const created = await server.videos.quickUpload({ name: 'video' })
- uuid = created.uuid
- })
-
- it('Should fail without a valid uuid', async function () {
- await server.videos.getSource({ id: '4da6fde3-88f7-4d16-b119-108df563d0b0', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should receive 404 when passing a non existing video id', async function () {
- await server.videos.getSource({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should not get the source as unauthenticated', async function () {
- await server.videos.getSource({ id: uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401, token: null })
- })
-
- it('Should not get the source with another user', async function () {
- await server.videos.getSource({ id: uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403, token: userToken })
- })
-
- it('Should succeed with the correct parameters get the source as another user', async function () {
- await server.videos.getSource({ id: uuid })
- })
- })
-
- describe('When updating source video file', function () {
- let userAccessToken: string
- let userId: number
-
- let videoId: string
- let userVideoId: string
-
- before(async function () {
- const res = await server.users.generate('user2')
- userAccessToken = res.token
- userId = res.userId
-
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoId = uuid
-
- await waitJobs([ server ])
- })
-
- it('Should fail if not enabled on the instance', async function () {
- await server.config.disableFileUpdate()
-
- await server.videos.replaceSourceFile({ videoId, fixture: 'video_short.mp4', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail on an unknown video', async function () {
- await server.config.enableFileUpdate()
-
- await server.videos.replaceSourceFile({ videoId: 404, fixture: 'video_short.mp4', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with an invalid video', async function () {
- await server.config.enableLive({ allowReplay: false })
-
- const { video } = await server.live.quickCreate({ saveReplay: false, permanentLive: true })
- await server.videos.replaceSourceFile({
- videoId: video.uuid,
- fixture: 'video_short.mp4',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail without token', async function () {
- await server.videos.replaceSourceFile({
- token: null,
- videoId,
- fixture: 'video_short.mp4',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another user', async function () {
- await server.videos.replaceSourceFile({
- token: userAccessToken,
- videoId,
- fixture: 'video_short.mp4',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an incorrect input file', async function () {
- await server.videos.replaceSourceFile({
- fixture: 'video_short_fake.webm',
- videoId,
- completedExpectedStatus: HttpStatusCode.UNPROCESSABLE_ENTITY_422
- })
-
- await server.videos.replaceSourceFile({
- fixture: 'video_short.mkv',
- videoId,
- expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415
- })
- })
-
- it('Should fail if quota is exceeded', async function () {
- this.timeout(60000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'user video' })
- userVideoId = uuid
- await waitJobs([ server ])
-
- await server.users.update({ userId, videoQuota: 1 })
- await server.videos.replaceSourceFile({
- token: userAccessToken,
- videoId: uuid,
- fixture: 'video_short.mp4',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct params', async function () {
- this.timeout(60000)
-
- await server.users.update({ userId, videoQuota: 1000 * 1000 * 1000 })
- await server.videos.replaceSourceFile({ videoId: userVideoId, fixture: 'video_short.mp4' })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-storyboards.ts b/server/tests/api/check-params/video-storyboards.ts
deleted file mode 100644
index c038e7370..000000000
--- a/server/tests/api/check-params/video-storyboards.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test video storyboards API validator', function () {
- let server: PeerTubeServer
-
- let publicVideo: { uuid: string }
- let privateVideo: { uuid: string }
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- publicVideo = await server.videos.quickUpload({ name: 'public' })
- privateVideo = await server.videos.quickUpload({ name: 'private', privacy: VideoPrivacy.PRIVATE })
- })
-
- it('Should fail without a valid uuid', async function () {
- await server.storyboard.list({ id: '4da6fde3-88f7-4d16-b119-108df563d0b0', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should receive 404 when passing a non existing video id', async function () {
- await server.storyboard.list({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should not get the private storyboard without the appropriate token', async function () {
- await server.storyboard.list({ id: privateVideo.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401, token: null })
- await server.storyboard.list({ id: publicVideo.uuid, expectedStatus: HttpStatusCode.OK_200, token: null })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await server.storyboard.list({ id: privateVideo.uuid })
- await server.storyboard.list({ id: publicVideo.uuid })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-studio.ts b/server/tests/api/check-params/video-studio.ts
deleted file mode 100644
index 4ac0d93ed..000000000
--- a/server/tests/api/check-params/video-studio.ts
+++ /dev/null
@@ -1,388 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, VideoStudioTask } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- VideoStudioCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video studio API validator', function () {
- let server: PeerTubeServer
- let command: VideoStudioCommand
- let userAccessToken: string
- let videoUUID: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- userAccessToken = await server.users.generateUserAndToken('user1')
-
- await server.config.enableMinimumTranscoding()
-
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
- videoUUID = uuid
-
- command = server.videoStudio
-
- await waitJobs([ server ])
- })
-
- describe('Task creation', function () {
-
- describe('Config settings', function () {
-
- it('Should fail if studio is disabled', async function () {
- await server.config.updateExistingSubConfig({
- newConfig: {
- videoStudio: {
- enabled: false
- }
- }
- })
-
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail to enable studio if transcoding is disabled', async function () {
- await server.config.updateExistingSubConfig({
- newConfig: {
- videoStudio: {
- enabled: true
- },
- transcoding: {
- enabled: false
- }
- },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed to enable video studio', async function () {
- await server.config.updateExistingSubConfig({
- newConfig: {
- videoStudio: {
- enabled: true
- },
- transcoding: {
- enabled: true
- }
- }
- })
- })
- })
-
- describe('Common tasks', function () {
-
- it('Should fail without token', async function () {
- await command.createEditionTasks({
- token: null,
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another user token', async function () {
- await command.createEditionTasks({
- token: userAccessToken,
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid video', async function () {
- await command.createEditionTasks({
- videoId: 'tintin',
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an unknown video', async function () {
- await command.createEditionTasks({
- videoId: 42,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with an already in transcoding state video', async function () {
- this.timeout(60000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'transcoded video' })
- await waitJobs([ server ])
-
- await server.jobs.pauseJobQueue()
- await server.videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
-
- await command.createEditionTasks({
- videoId: uuid,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
-
- await server.jobs.resumeJobQueue()
- })
-
- it('Should fail with a bad complex task', async function () {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'cut',
- options: {
- start: 1,
- end: 2
- }
- },
- {
- name: 'hadock',
- options: {
- start: 1,
- end: 2
- }
- }
- ] as any,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail without task', async function () {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [],
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with too many tasks', async function () {
- const tasks: VideoStudioTask[] = []
-
- for (let i = 0; i < 110; i++) {
- tasks.push({
- name: 'cut',
- options: {
- start: 1
- }
- })
- }
-
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with correct parameters', async function () {
- await server.jobs.pauseJobQueue()
-
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should fail with a video that is already waiting for edition', async function () {
- this.timeout(120000)
-
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: VideoStudioCommand.getComplexTask(),
- expectedStatus: HttpStatusCode.CONFLICT_409
- })
-
- await server.jobs.resumeJobQueue()
-
- await waitJobs([ server ])
- })
- })
-
- describe('Cut task', function () {
-
- async function cut (start: number, end: number, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'cut',
- options: {
- start,
- end
- }
- }
- ],
- expectedStatus
- })
- }
-
- it('Should fail with bad start/end', async function () {
- const invalid = [
- 'tintin',
- -1,
- undefined
- ]
-
- for (const value of invalid) {
- await cut(value as any, undefined)
- await cut(undefined, value as any)
- }
- })
-
- it('Should fail with the same start/end', async function () {
- await cut(2, 2)
- })
-
- it('Should fail with inconsistents start/end', async function () {
- await cut(2, 1)
- })
-
- it('Should fail without start and end', async function () {
- await cut(undefined, undefined)
- })
-
- it('Should succeed with the correct params', async function () {
- this.timeout(120000)
-
- await cut(0, 2, HttpStatusCode.NO_CONTENT_204)
-
- await waitJobs([ server ])
- })
- })
-
- describe('Watermark task', function () {
-
- async function addWatermark (file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'add-watermark',
- options: {
- file
- }
- }
- ],
- expectedStatus
- })
- }
-
- it('Should fail without waterkmark', async function () {
- await addWatermark(undefined)
- })
-
- it('Should fail with an invalid watermark', async function () {
- await addWatermark('video_short.mp4')
- })
-
- it('Should succeed with the correct params', async function () {
- this.timeout(120000)
-
- await addWatermark('custom-thumbnail.jpg', HttpStatusCode.NO_CONTENT_204)
-
- await waitJobs([ server ])
- })
- })
-
- describe('Intro/Outro task', function () {
-
- async function addIntroOutro (type: 'add-intro' | 'add-outro', file: string, expectedStatus = HttpStatusCode.BAD_REQUEST_400) {
- await command.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: type,
- options: {
- file
- }
- }
- ],
- expectedStatus
- })
- }
-
- it('Should fail without file', async function () {
- await addIntroOutro('add-intro', undefined)
- await addIntroOutro('add-outro', undefined)
- })
-
- it('Should fail with an invalid file', async function () {
- await addIntroOutro('add-intro', 'custom-thumbnail.jpg')
- await addIntroOutro('add-outro', 'custom-thumbnail.jpg')
- })
-
- it('Should fail with a file that does not contain video stream', async function () {
- await addIntroOutro('add-intro', 'sample.ogg')
- await addIntroOutro('add-outro', 'sample.ogg')
-
- })
-
- it('Should succeed with the correct params', async function () {
- this.timeout(120000)
-
- await addIntroOutro('add-intro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
-
- await addIntroOutro('add-outro', 'video_very_short_240p.mp4', HttpStatusCode.NO_CONTENT_204)
- await waitJobs([ server ])
- })
-
- it('Should check total quota when creating the task', async function () {
- this.timeout(120000)
-
- const user = await server.users.create({ username: 'user_quota_1' })
- const token = await server.login.getAccessToken('user_quota_1')
- const { uuid } = await server.videos.quickUpload({ token, name: 'video_quota_1', fixture: 'video_short.mp4' })
-
- const addIntroOutroByUser = (type: 'add-intro' | 'add-outro', expectedStatus: HttpStatusCode) => {
- return command.createEditionTasks({
- token,
- videoId: uuid,
- tasks: [
- {
- name: type,
- options: {
- file: 'video_short.mp4'
- }
- }
- ],
- expectedStatus
- })
- }
-
- await waitJobs([ server ])
-
- const { videoQuotaUsed } = await server.users.getMyQuotaUsed({ token })
- await server.users.update({ userId: user.id, videoQuota: Math.round(videoQuotaUsed * 2.5) })
-
- // Still valid
- await addIntroOutroByUser('add-intro', HttpStatusCode.NO_CONTENT_204)
-
- await waitJobs([ server ])
-
- // Too much quota
- await addIntroOutroByUser('add-intro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
- await addIntroOutroByUser('add-outro', HttpStatusCode.PAYLOAD_TOO_LARGE_413)
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/video-token.ts b/server/tests/api/check-params/video-token.ts
deleted file mode 100644
index 7cb3e84a2..000000000
--- a/server/tests/api/check-params/video-token.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test video tokens', function () {
- let server: PeerTubeServer
- let privateVideoId: string
- let passwordProtectedVideoId: string
- let userToken: string
-
- const videoPassword = 'password'
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(300_000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- {
- const { uuid } = await server.videos.quickUpload({ name: 'private video', privacy: VideoPrivacy.PRIVATE })
- privateVideoId = uuid
- }
- {
- const { uuid } = await server.videos.quickUpload({
- name: 'password protected video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ videoPassword ]
- })
- passwordProtectedVideoId = uuid
- }
- userToken = await server.users.generateUserAndToken('user1')
- })
-
- it('Should not generate tokens on private video for unauthenticated user', async function () {
- await server.videoToken.create({ videoId: privateVideoId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not generate tokens of unknown video', async function () {
- await server.videoToken.create({ videoId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should not generate tokens with incorrect password', async function () {
- await server.videoToken.create({
- videoId: passwordProtectedVideoId,
- token: null,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- videoPassword: 'incorrectPassword'
- })
- })
-
- it('Should not generate tokens of a non owned video', async function () {
- await server.videoToken.create({ videoId: privateVideoId, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should generate token', async function () {
- await server.videoToken.create({ videoId: privateVideoId })
- })
-
- it('Should generate token on password protected video', async function () {
- await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword, token: null })
- await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword, token: userToken })
- await server.videoToken.create({ videoId: passwordProtectedVideoId, videoPassword })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/videos-common-filters.ts b/server/tests/api/check-params/videos-common-filters.ts
deleted file mode 100644
index 603f7f777..000000000
--- a/server/tests/api/check-params/videos-common-filters.ts
+++ /dev/null
@@ -1,163 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, UserRole, VideoInclude, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test video filters validators', function () {
- let server: PeerTubeServer
- let userAccessToken: string
- let moderatorAccessToken: string
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- const user = { username: 'user1', password: 'my super password' }
- await server.users.create({ username: user.username, password: user.password })
- userAccessToken = await server.login.getAccessToken(user)
-
- const moderator = { username: 'moderator', password: 'my super password' }
- await server.users.create({ username: moderator.username, password: moderator.password, role: UserRole.MODERATOR })
-
- moderatorAccessToken = await server.login.getAccessToken(moderator)
- })
-
- describe('When setting video filters', function () {
-
- const validIncludes = [
- VideoInclude.NONE,
- VideoInclude.BLOCKED_OWNER,
- VideoInclude.NOT_PUBLISHED_STATE | VideoInclude.BLACKLISTED
- ]
-
- async function testEndpoints (options: {
- token?: string
- isLocal?: boolean
- include?: VideoInclude
- privacyOneOf?: VideoPrivacy[]
- expectedStatus: HttpStatusCode
- excludeAlreadyWatched?: boolean
- unauthenticatedUser?: boolean
- }) {
- const paths = [
- '/api/v1/video-channels/root_channel/videos',
- '/api/v1/accounts/root/videos',
- '/api/v1/videos',
- '/api/v1/search/videos'
- ]
-
- for (const path of paths) {
- const token = options.unauthenticatedUser
- ? undefined
- : options.token || server.accessToken
-
- await makeGetRequest({
- url: server.url,
- path,
- token,
- query: {
- isLocal: options.isLocal,
- privacyOneOf: options.privacyOneOf,
- include: options.include,
- excludeAlreadyWatched: options.excludeAlreadyWatched
- },
- expectedStatus: options.expectedStatus
- })
- }
- }
-
- it('Should fail with a bad privacyOneOf', async function () {
- await testEndpoints({ privacyOneOf: [ 'toto' ] as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with a good privacyOneOf', async function () {
- await testEndpoints({ privacyOneOf: [ VideoPrivacy.INTERNAL ], expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should fail to use privacyOneOf with a simple user', async function () {
- await testEndpoints({
- privacyOneOf: [ VideoPrivacy.INTERNAL ],
- token: userAccessToken,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with a bad include', async function () {
- await testEndpoints({ include: 'toto' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with a good include', async function () {
- for (const include of validIncludes) {
- await testEndpoints({ include, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should fail to include more videos with a simple user', async function () {
- for (const include of validIncludes) {
- await testEndpoints({ token: userAccessToken, include, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- }
- })
-
- it('Should succeed to list all local/all with a moderator', async function () {
- for (const include of validIncludes) {
- await testEndpoints({ token: moderatorAccessToken, include, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should succeed to list all local/all with an admin', async function () {
- for (const include of validIncludes) {
- await testEndpoints({ token: server.accessToken, include, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- // Because we cannot authenticate the user on the RSS endpoint
- it('Should fail on the feeds endpoint with the all filter', async function () {
- for (const include of [ VideoInclude.NOT_PUBLISHED_STATE ]) {
- await makeGetRequest({
- url: server.url,
- path: '/feeds/videos.json',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401,
- query: {
- include
- }
- })
- }
- })
-
- it('Should succeed on the feeds endpoint with the local filter', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/feeds/videos.json',
- expectedStatus: HttpStatusCode.OK_200,
- query: {
- isLocal: true
- }
- })
- })
-
- it('Should fail when trying to exclude already watched videos for an unlogged user', async function () {
- await testEndpoints({ excludeAlreadyWatched: true, unauthenticatedUser: true, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed when trying to exclude already watched videos for a logged user', async function () {
- await testEndpoints({ token: userAccessToken, excludeAlreadyWatched: true, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/videos-history.ts b/server/tests/api/check-params/videos-history.ts
deleted file mode 100644
index d96fe7ca9..000000000
--- a/server/tests/api/check-params/videos-history.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { checkBadCountPagination, checkBadStartPagination } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePostBodyRequest,
- makePutBodyRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test videos history API validator', function () {
- const myHistoryPath = '/api/v1/users/me/history/videos'
- const myHistoryRemove = myHistoryPath + '/remove'
- let viewPath: string
- let server: PeerTubeServer
- let videoId: number
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const { id, uuid } = await server.videos.upload()
- viewPath = '/api/v1/videos/' + uuid + '/views'
- videoId = id
- })
-
- describe('When notifying a user is watching a video', function () {
-
- it('Should fail with a bad token', async function () {
- const fields = { currentTime: 5 }
- await makePutBodyRequest({ url: server.url, path: viewPath, fields, token: 'bad', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- const fields = { currentTime: 5 }
-
- await makePutBodyRequest({
- url: server.url,
- path: viewPath,
- fields,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When listing user videos history', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, myHistoryPath, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, myHistoryPath, server.accessToken)
- })
-
- it('Should fail with an unauthenticated user', async function () {
- await makeGetRequest({ url: server.url, path: myHistoryPath, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should succeed with the correct params', async function () {
- await makeGetRequest({ url: server.url, token: server.accessToken, path: myHistoryPath, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When removing a specific user video history element', function () {
- let path: string
-
- before(function () {
- path = myHistoryPath + '/' + videoId
- })
-
- it('Should fail with an unauthenticated user', async function () {
- await makeDeleteRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a bad videoId parameter', async function () {
- await makeDeleteRequest({
- url: server.url,
- token: server.accessToken,
- path: myHistoryRemove + '/hi',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await makeDeleteRequest({
- url: server.url,
- token: server.accessToken,
- path,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When removing all user videos history', function () {
- it('Should fail with an unauthenticated user', async function () {
- await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with a bad beforeDate parameter', async function () {
- const body = { beforeDate: '15' }
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path: myHistoryRemove,
- fields: body,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with a valid beforeDate param', async function () {
- const body = { beforeDate: new Date().toISOString() }
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path: myHistoryRemove,
- fields: body,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
-
- it('Should succeed without body', async function () {
- await makePostBodyRequest({
- url: server.url,
- token: server.accessToken,
- path: myHistoryRemove,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/videos-overviews.ts b/server/tests/api/check-params/videos-overviews.ts
deleted file mode 100644
index ae7de24dd..000000000
--- a/server/tests/api/check-params/videos-overviews.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/server-commands'
-
-describe('Test videos overview API validator', function () {
- let server: PeerTubeServer
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- })
-
- describe('When getting videos overview', function () {
-
- it('Should fail with a bad pagination', async function () {
- await server.overviews.getVideos({ page: 0, expectedStatus: 400 })
- await server.overviews.getVideos({ page: 100, expectedStatus: 400 })
- })
-
- it('Should succeed with a good pagination', async function () {
- await server.overviews.getVideos({ page: 1 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
deleted file mode 100644
index f00698fe3..000000000
--- a/server/tests/api/check-params/videos.ts
+++ /dev/null
@@ -1,881 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { join } from 'path'
-import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, checkUploadVideoParam } from '@server/tests/shared'
-import { omit, randomInt, root } from '@shared/core-utils'
-import { HttpStatusCode, PeerTubeProblemDocument, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeDeleteRequest,
- makeGetRequest,
- makePutBodyRequest,
- makeUploadRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test videos API validator', function () {
- const path = '/api/v1/videos/'
- let server: PeerTubeServer
- let userAccessToken = ''
- let accountName: string
- let channelId: number
- let channelName: string
- let video: VideoCreateResult
- let privateVideo: VideoCreateResult
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- userAccessToken = await server.users.generateUserAndToken('user1')
-
- {
- const body = await server.users.getMyInfo()
- channelId = body.videoChannels[0].id
- channelName = body.videoChannels[0].name
- accountName = body.account.name + '@' + body.account.host
- }
-
- {
- privateVideo = await server.videos.quickUpload({ name: 'private video', privacy: VideoPrivacy.PRIVATE })
- }
- })
-
- describe('When listing videos', function () {
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path)
- })
-
- it('Should fail with a bad skipVideos query', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200, query: { skipCount: 'toto' } })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200, query: { skipCount: false } })
- })
- })
-
- describe('When searching a video', function () {
-
- it('Should fail with nothing', async function () {
- await makeGetRequest({
- url: server.url,
- path: join(path, 'search'),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, join(path, 'search', 'test'))
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, join(path, 'search', 'test'))
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, join(path, 'search', 'test'))
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When listing my videos', function () {
- const path = '/api/v1/users/me/videos'
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an invalid channel', async function () {
- await makeGetRequest({ url: server.url, token: server.accessToken, path, query: { channelId: 'toto' } })
- })
-
- it('Should fail with an unknown channel', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path,
- query: { channelId: 89898 },
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, token: server.accessToken, path, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When listing account videos', function () {
- let path: string
-
- before(async function () {
- path = '/api/v1/accounts/' + accountName + '/videos'
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When listing video channel videos', function () {
- let path: string
-
- before(async function () {
- path = '/api/v1/video-channels/' + channelName + '/videos'
- })
-
- it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
- })
-
- it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
- })
-
- it('Should success with the correct parameters', async function () {
- await makeGetRequest({ url: server.url, path, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('When adding a video', function () {
- let baseCorrectParams
- const baseCorrectAttaches = {
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.webm')
- }
-
- before(function () {
- // Put in before to have channelId
- baseCorrectParams = {
- name: 'my super name',
- category: 5,
- licence: 1,
- language: 'pt',
- nsfw: false,
- commentsEnabled: true,
- downloadEnabled: true,
- waitTranscoding: true,
- description: 'my super description',
- support: 'my super support text',
- tags: [ 'tag1', 'tag2' ],
- privacy: VideoPrivacy.PUBLIC,
- channelId,
- originallyPublishedAt: new Date().toISOString()
- }
- })
-
- function runSuite (mode: 'legacy' | 'resumable') {
-
- const baseOptions = () => {
- return {
- server,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400,
- mode
- }
- }
-
- it('Should fail with nothing', async function () {
- const fields = {}
- const attaches = {}
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail without name', async function () {
- const fields = omit(baseCorrectParams, [ 'name' ])
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad category', async function () {
- const fields = { ...baseCorrectParams, category: 125 }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad licence', async function () {
- const fields = { ...baseCorrectParams, licence: 125 }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad language', async function () {
- const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail without a channel', async function () {
- const fields = omit(baseCorrectParams, [ 'channelId' ])
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad channel', async function () {
- const fields = { ...baseCorrectParams, channelId: 545454 }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with another user channel', async function () {
- const user = {
- username: 'fake' + randomInt(0, 1500),
- password: 'fake_password'
- }
- await server.users.create({ username: user.username, password: user.password })
-
- const accessTokenUser = await server.login.getAccessToken(user)
- const { videoChannels } = await server.users.getMyInfo({ token: accessTokenUser })
- const customChannelId = videoChannels[0].id
-
- const fields = { ...baseCorrectParams, channelId: customChannelId }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({
- ...baseOptions(),
- token: userAccessToken,
- attributes: { ...fields, ...attaches }
- })
- })
-
- it('Should fail with too many tags', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a tag length too low', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a tag length too big', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad schedule update (miss updateAt)', async function () {
- const fields = { ...baseCorrectParams, scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad schedule update (wrong updateAt)', async function () {
- const fields = {
- ...baseCorrectParams,
-
- scheduleUpdate: {
- privacy: VideoPrivacy.PUBLIC,
- updateAt: 'toto'
- }
- }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a bad originally published at attribute', async function () {
- const fields = { ...baseCorrectParams, originallyPublishedAt: 'toto' }
- const attaches = baseCorrectAttaches
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail without an input file', async function () {
- const fields = baseCorrectParams
- const attaches = {}
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with an incorrect input file', async function () {
- const fields = baseCorrectParams
- let attaches = { fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm') }
-
- await checkUploadVideoParam({
- ...baseOptions(),
- attributes: { ...fields, ...attaches },
- // 200 for the init request, 422 when the file has finished being uploaded
- expectedStatus: undefined,
- completedExpectedStatus: HttpStatusCode.UNPROCESSABLE_ENTITY_422
- })
-
- attaches = { fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv') }
- await checkUploadVideoParam({
- ...baseOptions(),
- attributes: { ...fields, ...attaches },
- expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415
- })
- })
-
- it('Should fail with an incorrect thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4'),
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a big thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: join(root(), 'server', 'tests', 'fixtures', 'custom-preview-big.png'),
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with an incorrect preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4'),
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should fail with a big preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: join(root(), 'server', 'tests', 'fixtures', 'custom-preview-big.png'),
- fixture: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await checkUploadVideoParam({ ...baseOptions(), attributes: { ...fields, ...attaches } })
- })
-
- it('Should report the appropriate error', async function () {
- const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
- const attaches = baseCorrectAttaches
-
- const attributes = { ...fields, ...attaches }
- const body = await checkUploadVideoParam({ ...baseOptions(), attributes })
-
- const error = body as unknown as PeerTubeProblemDocument
-
- if (mode === 'legacy') {
- expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy')
- } else {
- expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit')
- }
-
- expect(error.type).to.equal('about:blank')
- expect(error.title).to.equal('Bad Request')
-
- expect(error.detail).to.equal('Incorrect request parameters: language')
- expect(error.error).to.equal('Incorrect request parameters: language')
-
- expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400)
- expect(error['invalid-params'].language).to.exist
- })
-
- it('Should succeed with the correct parameters', async function () {
- this.timeout(30000)
-
- const fields = baseCorrectParams
-
- {
- const attaches = baseCorrectAttaches
- await checkUploadVideoParam({
- ...baseOptions(),
- attributes: { ...fields, ...attaches },
- expectedStatus: HttpStatusCode.OK_200
- })
- }
-
- {
- const attaches = {
- ...baseCorrectAttaches,
-
- videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await checkUploadVideoParam({
- ...baseOptions(),
- attributes: { ...fields, ...attaches },
- expectedStatus: HttpStatusCode.OK_200
- })
- }
-
- {
- const attaches = {
- ...baseCorrectAttaches,
-
- videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.ogv')
- }
-
- await checkUploadVideoParam({
- ...baseOptions(),
- attributes: { ...fields, ...attaches },
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- })
- }
-
- describe('Resumable upload', function () {
- runSuite('resumable')
- })
-
- describe('Legacy upload', function () {
- runSuite('legacy')
- })
- })
-
- describe('When updating a video', function () {
- const baseCorrectParams = {
- name: 'my super name',
- category: 5,
- licence: 2,
- language: 'pt',
- nsfw: false,
- commentsEnabled: false,
- downloadEnabled: false,
- description: 'my super description',
- privacy: VideoPrivacy.PUBLIC,
- tags: [ 'tag1', 'tag2' ]
- }
-
- before(async function () {
- const { data } = await server.videos.list()
- video = data[0]
- })
-
- it('Should fail with nothing', async function () {
- const fields = {}
- await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
- })
-
- it('Should fail without a valid uuid', async function () {
- const fields = baseCorrectParams
- await makePutBodyRequest({ url: server.url, path: path + 'blabla', token: server.accessToken, fields })
- })
-
- it('Should fail with an unknown id', async function () {
- const fields = baseCorrectParams
-
- await makePutBodyRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06',
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a long name', async function () {
- const fields = { ...baseCorrectParams, name: 'super'.repeat(65) }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad category', async function () {
- const fields = { ...baseCorrectParams, category: 125 }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad licence', async function () {
- const fields = { ...baseCorrectParams, licence: 125 }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad language', async function () {
- const fields = { ...baseCorrectParams, language: 'a'.repeat(15) }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a long description', async function () {
- const fields = { ...baseCorrectParams, description: 'super'.repeat(2500) }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a long support text', async function () {
- const fields = { ...baseCorrectParams, support: 'super'.repeat(201) }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad channel', async function () {
- const fields = { ...baseCorrectParams, channelId: 545454 }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with too many tags', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6' ] }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too low', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 't' ] }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a tag length too big', async function () {
- const fields = { ...baseCorrectParams, tags: [ 'tag1', 'my_super_tag_too_long_long_long_long_long_long' ] }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad schedule update (miss updateAt)', async function () {
- const fields = { ...baseCorrectParams, scheduleUpdate: { privacy: VideoPrivacy.PUBLIC } }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad schedule update (wrong updateAt)', async function () {
- const fields = { ...baseCorrectParams, scheduleUpdate: { updateAt: 'toto', privacy: VideoPrivacy.PUBLIC } }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with a bad originally published at param', async function () {
- const fields = { ...baseCorrectParams, originallyPublishedAt: 'toto' }
-
- await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- })
-
- it('Should fail with an incorrect thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await makeUploadRequest({
- url: server.url,
- method: 'PUT',
- path: path + video.shortUUID,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with a big thumbnail file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- thumbnailfile: join(root(), 'server', 'tests', 'fixtures', 'custom-preview-big.png')
- }
-
- await makeUploadRequest({
- url: server.url,
- method: 'PUT',
- path: path + video.shortUUID,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with an incorrect preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mp4')
- }
-
- await makeUploadRequest({
- url: server.url,
- method: 'PUT',
- path: path + video.shortUUID,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with a big preview file', async function () {
- const fields = baseCorrectParams
- const attaches = {
- previewfile: join(root(), 'server', 'tests', 'fixtures', 'custom-preview-big.png')
- }
-
- await makeUploadRequest({
- url: server.url,
- method: 'PUT',
- path: path + video.shortUUID,
- token: server.accessToken,
- fields,
- attaches
- })
- })
-
- it('Should fail with a video of another user without the appropriate right', async function () {
- const fields = baseCorrectParams
-
- await makePutBodyRequest({
- url: server.url,
- path: path + video.shortUUID,
- token: userAccessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with a video of another server')
-
- it('Shoud report the appropriate error', async function () {
- const fields = { ...baseCorrectParams, licence: 125 }
-
- const res = await makePutBodyRequest({ url: server.url, path: path + video.shortUUID, token: server.accessToken, fields })
- const error = res.body as PeerTubeProblemDocument
-
- expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo')
-
- expect(error.type).to.equal('about:blank')
- expect(error.title).to.equal('Bad Request')
-
- expect(error.detail).to.equal('Incorrect request parameters: licence')
- expect(error.error).to.equal('Incorrect request parameters: licence')
-
- expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400)
- expect(error['invalid-params'].licence).to.exist
- })
-
- it('Should succeed with the correct parameters', async function () {
- const fields = baseCorrectParams
-
- await makePutBodyRequest({
- url: server.url,
- path: path + video.shortUUID,
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When getting a video', function () {
- it('Should return the list of the videos with nothing', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.data).to.be.an('array')
- expect(res.body.data.length).to.equal(6)
- })
-
- it('Should fail without a correct uuid', async function () {
- await server.videos.get({ id: 'coucou', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should return 404 with an incorrect video', async function () {
- await server.videos.get({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Shoud report the appropriate error', async function () {
- const body = await server.videos.get({ id: 'hi', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- const error = body as unknown as PeerTubeProblemDocument
-
- expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo')
-
- expect(error.type).to.equal('about:blank')
- expect(error.title).to.equal('Bad Request')
-
- expect(error.detail).to.equal('Incorrect request parameters: id')
- expect(error.error).to.equal('Incorrect request parameters: id')
-
- expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400)
- expect(error['invalid-params'].id).to.exist
- })
-
- it('Should succeed with the correct parameters', async function () {
- await server.videos.get({ id: video.shortUUID })
- })
- })
-
- describe('When rating a video', function () {
- let videoId: number
-
- before(async function () {
- const { data } = await server.videos.list()
- videoId = data[0].id
- })
-
- it('Should fail without a valid uuid', async function () {
- const fields = {
- rating: 'like'
- }
- await makePutBodyRequest({ url: server.url, path: path + 'blabla/rate', token: server.accessToken, fields })
- })
-
- it('Should fail with an unknown id', async function () {
- const fields = {
- rating: 'like'
- }
- await makePutBodyRequest({
- url: server.url,
- path: path + '4da6fde3-88f7-4d16-b119-108df5630b06/rate',
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should fail with a wrong rating', async function () {
- const fields = {
- rating: 'likes'
- }
- await makePutBodyRequest({ url: server.url, path: path + videoId + '/rate', token: server.accessToken, fields })
- })
-
- it('Should fail with a private video of another user', async function () {
- const fields = {
- rating: 'like'
- }
- await makePutBodyRequest({
- url: server.url,
- path: path + privateVideo.uuid + '/rate',
- token: userAccessToken,
- fields,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- const fields = {
- rating: 'like'
- }
- await makePutBodyRequest({
- url: server.url,
- path: path + videoId + '/rate',
- token: server.accessToken,
- fields,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
- })
- })
-
- describe('When removing a video', function () {
- it('Should have 404 with nothing', async function () {
- await makeDeleteRequest({
- url: server.url,
- path,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail without a correct uuid', async function () {
- await server.videos.remove({ id: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with a video which does not exist', async function () {
- await server.videos.remove({ id: '4da6fde3-88f7-4d16-b119-108df5630b06', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should fail with a video of another user without the appropriate right', async function () {
- await server.videos.remove({ token: userAccessToken, id: video.uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail with a video of another server')
-
- it('Shoud report the appropriate error', async function () {
- const body = await server.videos.remove({ id: 'hello', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- const error = body as PeerTubeProblemDocument
-
- expect(error.docs).to.equal('https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo')
-
- expect(error.type).to.equal('about:blank')
- expect(error.title).to.equal('Bad Request')
-
- expect(error.detail).to.equal('Incorrect request parameters: id')
- expect(error.error).to.equal('Incorrect request parameters: id')
-
- expect(error.status).to.equal(HttpStatusCode.BAD_REQUEST_400)
- expect(error['invalid-params'].id).to.exist
- })
-
- it('Should succeed with the correct parameters', async function () {
- await server.videos.remove({ id: video.uuid })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/check-params/views.ts b/server/tests/api/check-params/views.ts
deleted file mode 100644
index 11416ccb8..000000000
--- a/server/tests/api/check-params/views.ts
+++ /dev/null
@@ -1,227 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test videos views', function () {
- let servers: PeerTubeServer[]
- let liveVideoId: string
- let videoId: string
- let remoteVideoId: string
- let userAccessToken: string
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.enableLive({ allowReplay: false, transcoding: false });
-
- ({ uuid: videoId } = await servers[0].videos.quickUpload({ name: 'video' }));
- ({ uuid: remoteVideoId } = await servers[1].videos.quickUpload({ name: 'video' }));
- ({ uuid: liveVideoId } = await servers[0].live.create({
- fields: {
- name: 'live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id
- }
- }))
-
- userAccessToken = await servers[0].users.generateUserAndToken('user')
-
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('When viewing a video', async function () {
-
- it('Should fail without current time', async function () {
- await servers[0].views.view({ id: videoId, currentTime: undefined, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an invalid current time', async function () {
- await servers[0].views.view({ id: videoId, currentTime: -1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await servers[0].views.view({ id: videoId, currentTime: 10, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with correct parameters', async function () {
- await servers[0].views.view({ id: videoId, currentTime: 1 })
- })
- })
-
- describe('When getting overall stats', function () {
-
- it('Should fail with a remote video', async function () {
- await servers[0].videoStats.getOverallStats({ videoId: remoteVideoId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should fail without token', async function () {
- await servers[0].videoStats.getOverallStats({ videoId, token: null, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should fail with another token', async function () {
- await servers[0].videoStats.getOverallStats({
- videoId,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid start date', async function () {
- await servers[0].videoStats.getOverallStats({
- videoId,
- startDate: 'fake' as any,
- endDate: new Date().toISOString(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an invalid end date', async function () {
- await servers[0].videoStats.getOverallStats({
- videoId,
- startDate: new Date().toISOString(),
- endDate: 'fake' as any,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await servers[0].videoStats.getOverallStats({
- videoId,
- startDate: new Date().toISOString(),
- endDate: new Date().toISOString()
- })
- })
- })
-
- describe('When getting timeserie stats', function () {
-
- it('Should fail with a remote video', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId: remoteVideoId,
- metric: 'viewers',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail without token', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- token: null,
- metric: 'viewers',
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another token', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- token: userAccessToken,
- metric: 'viewers',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail with an invalid metric', async function () {
- await servers[0].videoStats.getTimeserieStats({ videoId, metric: 'hello' as any, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should fail with an invalid start date', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- metric: 'viewers',
- startDate: 'fake' as any,
- endDate: new Date(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with an invalid end date', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- metric: 'viewers',
- startDate: new Date(),
- endDate: 'fake' as any,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if start date is specified but not end date', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- metric: 'viewers',
- startDate: new Date(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail if end date is specified but not start date', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- metric: 'viewers',
- endDate: new Date(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should fail with a too big interval', async function () {
- await servers[0].videoStats.getTimeserieStats({
- videoId,
- metric: 'viewers',
- startDate: new Date('2000-04-07T08:31:57.126Z'),
- endDate: new Date(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await servers[0].videoStats.getTimeserieStats({ videoId, metric: 'viewers' })
- })
- })
-
- describe('When getting retention stats', function () {
-
- it('Should fail with a remote video', async function () {
- await servers[0].videoStats.getRetentionStats({
- videoId: remoteVideoId,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail without token', async function () {
- await servers[0].videoStats.getRetentionStats({
- videoId,
- token: null,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
- })
-
- it('Should fail with another token', async function () {
- await servers[0].videoStats.getRetentionStats({
- videoId,
- token: userAccessToken,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should fail on live video', async function () {
- await servers[0].videoStats.getRetentionStats({ videoId: liveVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should succeed with the correct parameters', async function () {
- await servers[0].videoStats.getRetentionStats({ videoId })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/index.ts b/server/tests/api/index.ts
deleted file mode 100644
index ef0c83294..000000000
--- a/server/tests/api/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Order of the tests we want to execute
-import './activitypub'
-import './check-params'
-import './moderation'
-import './object-storage'
-import './notifications'
-import './redundancy'
-import './runners'
-import './search'
-import './server'
-import './transcoding'
-import './users'
-import './videos'
diff --git a/server/tests/api/live/index.ts b/server/tests/api/live/index.ts
deleted file mode 100644
index c88943f65..000000000
--- a/server/tests/api/live/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import './live-constraints'
-import './live-fast-restream'
-import './live-socket-messages'
-import './live-permanent'
-import './live-rtmps'
-import './live-save-replay'
-import './live'
diff --git a/server/tests/api/live/live-constraints.ts b/server/tests/api/live/live-constraints.ts
deleted file mode 100644
index 697d808d5..000000000
--- a/server/tests/api/live/live-constraints.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { LiveVideoError, UserVideoQuota, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs,
- waitUntilLiveReplacedByReplayOnAllServers,
- waitUntilLiveWaitingOnAllServers
-} from '@shared/server-commands'
-import { checkLiveCleanup } from '../../shared'
-
-describe('Test live constraints', function () {
- let servers: PeerTubeServer[] = []
- let userId: number
- let userAccessToken: string
- let userChannelId: number
-
- async function createLiveWrapper (options: { replay: boolean, permanent: boolean }) {
- const { replay, permanent } = options
-
- const liveAttributes = {
- name: 'user live',
- channelId: userChannelId,
- privacy: VideoPrivacy.PUBLIC,
- saveReplay: replay,
- replaySettings: options.replay ? { privacy: VideoPrivacy.PUBLIC } : undefined,
- permanentLive: permanent
- }
-
- const { uuid } = await servers[0].live.create({ token: userAccessToken, fields: liveAttributes })
- return uuid
- }
-
- async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoId })
- expect(video.isLive).to.be.false
- expect(video.duration).to.be.greaterThan(0)
- }
-
- await checkLiveCleanup({ server: servers[0], permanent: false, videoUUID: videoId, savedResolutions: resolutions })
- }
-
- function updateQuota (options: { total: number, daily: number }) {
- return servers[0].users.update({
- userId,
- videoQuota: options.total,
- videoQuotaDaily: options.daily
- })
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
- }
- }
- }
- })
-
- {
- const res = await servers[0].users.generate('user1')
- userId = res.userId
- userChannelId = res.userChannelId
- userAccessToken = res.token
-
- await updateQuota({ total: 1, daily: -1 })
- }
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should not have size limit if save replay is disabled', async function () {
- this.timeout(60000)
-
- const userVideoLiveoId = await createLiveWrapper({ replay: false, permanent: false })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
- })
-
- it('Should have size limit depending on user global quota if save replay is enabled on non permanent live', async function () {
- this.timeout(60000)
-
- // Wait for user quota memoize cache invalidation
- await wait(5000)
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, userVideoLiveoId)
- await waitJobs(servers)
-
- await checkSaveReplay(userVideoLiveoId)
-
- const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
- expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
- })
-
- it('Should have size limit depending on user global quota if save replay is enabled on a permanent live', async function () {
- this.timeout(60000)
-
- // Wait for user quota memoize cache invalidation
- await wait(5000)
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: true })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
-
- await waitJobs(servers)
- await waitUntilLiveWaitingOnAllServers(servers, userVideoLiveoId)
-
- const session = await servers[0].live.findLatestSession({ videoId: userVideoLiveoId })
- expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
- })
-
- it('Should have size limit depending on user daily quota if save replay is enabled', async function () {
- this.timeout(60000)
-
- // Wait for user quota memoize cache invalidation
- await wait(5000)
-
- await updateQuota({ total: -1, daily: 1 })
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, userVideoLiveoId)
- await waitJobs(servers)
-
- await checkSaveReplay(userVideoLiveoId)
-
- const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
- expect(session.error).to.equal(LiveVideoError.QUOTA_EXCEEDED)
- })
-
- it('Should succeed without quota limit', async function () {
- this.timeout(60000)
-
- // Wait for user quota memoize cache invalidation
- await wait(5000)
-
- await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
- })
-
- it('Should have the same quota in admin and as a user', async function () {
- this.timeout(120000)
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ token: userAccessToken, videoId: userVideoLiveoId })
-
- await servers[0].live.waitUntilPublished({ videoId: userVideoLiveoId })
- // Wait previous live cleanups
- await wait(3000)
-
- const baseQuota = await servers[0].users.getMyQuotaUsed({ token: userAccessToken })
-
- let quotaUser: UserVideoQuota
-
- do {
- await wait(500)
-
- quotaUser = await servers[0].users.getMyQuotaUsed({ token: userAccessToken })
- } while (quotaUser.videoQuotaUsed <= baseQuota.videoQuotaUsed)
-
- const { data } = await servers[0].users.list()
- const quotaAdmin = data.find(u => u.username === 'user1')
-
- expect(quotaUser.videoQuotaUsed).to.be.above(baseQuota.videoQuotaUsed)
- expect(quotaUser.videoQuotaUsedDaily).to.be.above(baseQuota.videoQuotaUsedDaily)
-
- expect(quotaAdmin.videoQuotaUsed).to.be.above(baseQuota.videoQuotaUsed)
- expect(quotaAdmin.videoQuotaUsedDaily).to.be.above(baseQuota.videoQuotaUsedDaily)
-
- expect(quotaUser.videoQuotaUsed).to.be.above(10)
- expect(quotaUser.videoQuotaUsedDaily).to.be.above(10)
- expect(quotaAdmin.videoQuotaUsed).to.be.above(10)
- expect(quotaAdmin.videoQuotaUsedDaily).to.be.above(10)
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have max duration limit', async function () {
- this.timeout(240000)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: 15,
- transcoding: {
- enabled: true,
- resolutions: ConfigCommand.getCustomConfigResolutions(true)
- }
- }
- }
- })
-
- const userVideoLiveoId = await createLiveWrapper({ replay: true, permanent: false })
- await servers[0].live.runAndTestStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, userVideoLiveoId)
- await waitJobs(servers)
-
- await checkSaveReplay(userVideoLiveoId, [ 720, 480, 360, 240, 144 ])
-
- const session = await servers[0].live.getReplaySession({ videoId: userVideoLiveoId })
- expect(session.error).to.equal(LiveVideoError.DURATION_EXCEEDED)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/live/live-fast-restream.ts b/server/tests/api/live/live-fast-restream.ts
deleted file mode 100644
index 1b7fddd8b..000000000
--- a/server/tests/api/live/live-fast-restream.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { LiveVideoCreate, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Fast restream in live', function () {
- let server: PeerTubeServer
-
- async function createLiveWrapper (options: { permanent: boolean, replay: boolean }) {
- const attributes: LiveVideoCreate = {
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- name: 'my super live',
- saveReplay: options.replay,
- replaySettings: options.replay ? { privacy: VideoPrivacy.PUBLIC } : undefined,
- permanentLive: options.permanent
- }
-
- const { uuid } = await server.live.create({ fields: attributes })
- return uuid
- }
-
- async function fastRestreamWrapper ({ replay }: { replay: boolean }) {
- const liveVideoUUID = await createLiveWrapper({ permanent: true, replay })
- await waitJobs([ server ])
-
- const rtmpOptions = {
- videoId: liveVideoUUID,
- copyCodecs: true,
- fixtureName: 'video_short.mp4'
- }
-
- // Streaming session #1
- let ffmpegCommand = await server.live.sendRTMPStreamInVideo(rtmpOptions)
- await server.live.waitUntilPublished({ videoId: liveVideoUUID })
-
- const video = await server.videos.get({ id: liveVideoUUID })
- const session1PlaylistId = video.streamingPlaylists[0].id
-
- await stopFfmpeg(ffmpegCommand)
- await server.live.waitUntilWaiting({ videoId: liveVideoUUID })
-
- // Streaming session #2
- ffmpegCommand = await server.live.sendRTMPStreamInVideo(rtmpOptions)
-
- let hasNewPlaylist = false
- do {
- const video = await server.videos.get({ id: liveVideoUUID })
- hasNewPlaylist = video.streamingPlaylists.length === 1 && video.streamingPlaylists[0].id !== session1PlaylistId
-
- await wait(100)
- } while (!hasNewPlaylist)
-
- await server.live.waitUntilSegmentGeneration({
- server,
- videoUUID: liveVideoUUID,
- segment: 1,
- playlistNumber: 0
- })
-
- return { ffmpegCommand, liveVideoUUID }
- }
-
- async function ensureLastLiveWorks (liveId: string) {
- // Equivalent to PEERTUBE_TEST_CONSTANTS_VIDEO_LIVE_CLEANUP_DELAY
- for (let i = 0; i < 100; i++) {
- const video = await server.videos.get({ id: liveId })
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- try {
- await server.live.getSegmentFile({ videoUUID: liveId, segment: 0, playlistNumber: 0 })
- await server.streamingPlaylists.get({ url: video.streamingPlaylists[0].playlistUrl })
- await server.streamingPlaylists.getSegmentSha256({ url: video.streamingPlaylists[0].segmentsSha256Url })
- } catch (err) {
- // FIXME: try to debug error in CI "Unexpected end of JSON input"
- console.error(err)
- throw err
- }
-
- await wait(100)
- }
- }
-
- async function runTest (replay: boolean) {
- const { ffmpegCommand, liveVideoUUID } = await fastRestreamWrapper({ replay })
-
- // TODO: remove, we try to debug a test timeout failure here
- console.log('Ensuring last live works')
-
- await ensureLastLiveWorks(liveVideoUUID)
-
- await stopFfmpeg(ffmpegCommand)
- await server.live.waitUntilWaiting({ videoId: liveVideoUUID })
-
- // Wait for replays
- await waitJobs([ server ])
-
- const { total, data: sessions } = await server.live.listSessions({ videoId: liveVideoUUID })
-
- expect(total).to.equal(2)
- expect(sessions).to.have.lengthOf(2)
-
- for (const session of sessions) {
- expect(session.error).to.be.null
-
- if (replay) {
- expect(session.replayVideo).to.exist
-
- await server.videos.get({ id: session.replayVideo.uuid })
- } else {
- expect(session.replayVideo).to.not.exist
- }
- }
- }
-
- before(async function () {
- this.timeout(120000)
-
- const env = { PEERTUBE_TEST_CONSTANTS_VIDEO_LIVE_CLEANUP_DELAY: '10000' }
- server = await createSingleServer(1, {}, { env })
-
- // Get the access tokens
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableMinimumTranscoding({ webVideo: false, hls: true })
- await server.config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' })
- })
-
- it('Should correctly fast restream in a permanent live with and without save replay', async function () {
- this.timeout(480000)
-
- // A test can take a long time, so prefer to run them in parallel
- await Promise.all([
- runTest(true),
- runTest(false)
- ])
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/live/live-permanent.ts b/server/tests/api/live/live-permanent.ts
deleted file mode 100644
index 4203b1bfc..000000000
--- a/server/tests/api/live/live-permanent.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkLiveCleanup } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Permanent live', function () {
- let servers: PeerTubeServer[] = []
- let videoUUID: string
-
- async function createLiveWrapper (permanentLive: boolean) {
- const attributes: LiveVideoCreate = {
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- name: 'my super live',
- saveReplay: false,
- permanentLive
- }
-
- const { uuid } = await servers[0].live.create({ fields: attributes })
- return uuid
- }
-
- async function checkVideoState (videoId: string, state: VideoState) {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoId })
- expect(video.state.id).to.equal(state)
- }
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
- enabled: true,
- resolutions: ConfigCommand.getCustomConfigResolutions(true)
- }
- }
- }
- })
- })
-
- it('Should create a non permanent live and update it to be a permanent live', async function () {
- this.timeout(20000)
-
- const videoUUID = await createLiveWrapper(false)
-
- {
- const live = await servers[0].live.get({ videoId: videoUUID })
- expect(live.permanentLive).to.be.false
- }
-
- await servers[0].live.update({ videoId: videoUUID, fields: { permanentLive: true } })
-
- {
- const live = await servers[0].live.get({ videoId: videoUUID })
- expect(live.permanentLive).to.be.true
- }
- })
-
- it('Should create a permanent live', async function () {
- this.timeout(20000)
-
- videoUUID = await createLiveWrapper(true)
-
- const live = await servers[0].live.get({ videoId: videoUUID })
- expect(live.permanentLive).to.be.true
-
- await waitJobs(servers)
- })
-
- it('Should stream into this permanent live', async function () {
- this.timeout(240_000)
-
- const beforePublication = new Date()
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
-
- for (const server of servers) {
- await server.live.waitUntilPublished({ videoId: videoUUID })
- }
-
- await checkVideoState(videoUUID, VideoState.PUBLISHED)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(new Date(video.publishedAt)).greaterThan(beforePublication)
- }
-
- await stopFfmpeg(ffmpegCommand)
- await servers[0].live.waitUntilWaiting({ videoId: videoUUID })
-
- await waitJobs(servers)
- })
-
- it('Should have cleaned up this live', async function () {
- this.timeout(40000)
-
- await wait(5000)
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(0)
- }
-
- await checkLiveCleanup({ server: servers[0], permanent: true, videoUUID })
- })
-
- it('Should have set this live to waiting for live state', async function () {
- this.timeout(20000)
-
- await checkVideoState(videoUUID, VideoState.WAITING_FOR_LIVE)
- })
-
- it('Should be able to stream again in the permanent live', async function () {
- this.timeout(60000)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
- enabled: true,
- resolutions: ConfigCommand.getCustomConfigResolutions(false)
- }
- }
- }
- })
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
-
- for (const server of servers) {
- await server.live.waitUntilPublished({ videoId: videoUUID })
- }
-
- await checkVideoState(videoUUID, VideoState.PUBLISHED)
-
- const count = await servers[0].live.countPlaylists({ videoUUID })
- // master playlist and 720p playlist
- expect(count).to.equal(2)
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have appropriate sessions', async function () {
- this.timeout(60000)
-
- await servers[0].live.waitUntilWaiting({ videoId: videoUUID })
-
- const { data, total } = await servers[0].live.listSessions({ videoId: videoUUID })
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const session of data) {
- expect(session.startDate).to.exist
- expect(session.endDate).to.exist
-
- expect(session.error).to.not.exist
- }
- })
-
- it('Should remove the live and have cleaned up the directory', async function () {
- this.timeout(60000)
-
- await servers[0].videos.remove({ id: videoUUID })
- await waitJobs(servers)
-
- await checkLiveCleanup({ server: servers[0], permanent: true, videoUUID })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/live/live-rtmps.ts b/server/tests/api/live/live-rtmps.ts
deleted file mode 100644
index dcaee90cf..000000000
--- a/server/tests/api/live/live-rtmps.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- testFfmpegStreamError,
- waitUntilLivePublishedOnAllServers
-} from '@shared/server-commands'
-
-describe('Test live RTMPS', function () {
- let server: PeerTubeServer
- let rtmpUrl: string
- let rtmpsUrl: string
-
- async function createLiveWrapper () {
- const liveAttributes = {
- name: 'live',
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- saveReplay: false
- }
-
- const { uuid } = await server.live.create({ fields: liveAttributes })
-
- const live = await server.live.get({ videoId: uuid })
- const video = await server.videos.get({ id: uuid })
-
- return Object.assign(video, live)
- }
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- // Get the access tokens
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
- }
- }
- }
- })
-
- rtmpUrl = 'rtmp://' + server.hostname + ':' + server.rtmpPort + '/live'
- rtmpsUrl = 'rtmps://' + server.hostname + ':' + server.rtmpsPort + '/live'
- })
-
- it('Should enable RTMPS endpoint only', async function () {
- this.timeout(240000)
-
- await server.kill()
- await server.run({
- live: {
- rtmp: {
- enabled: false
- },
- rtmps: {
- enabled: true,
- port: server.rtmpsPort,
- key_file: buildAbsoluteFixturePath('rtmps.key'),
- cert_file: buildAbsoluteFixturePath('rtmps.cert')
- }
- }
- })
-
- {
- const liveVideo = await createLiveWrapper()
-
- expect(liveVideo.rtmpUrl).to.not.exist
- expect(liveVideo.rtmpsUrl).to.equal(rtmpsUrl)
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl, streamKey: liveVideo.streamKey })
- await testFfmpegStreamError(command, true)
- }
-
- {
- const liveVideo = await createLiveWrapper()
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpsUrl, streamKey: liveVideo.streamKey })
- await waitUntilLivePublishedOnAllServers([ server ], liveVideo.uuid)
- await stopFfmpeg(command)
- }
- })
-
- it('Should enable both RTMP and RTMPS', async function () {
- this.timeout(240000)
-
- await server.kill()
- await server.run({
- live: {
- rtmp: {
- enabled: true,
- port: server.rtmpPort
- },
- rtmps: {
- enabled: true,
- port: server.rtmpsPort,
- key_file: buildAbsoluteFixturePath('rtmps.key'),
- cert_file: buildAbsoluteFixturePath('rtmps.cert')
- }
- }
- })
-
- {
- const liveVideo = await createLiveWrapper()
-
- expect(liveVideo.rtmpUrl).to.equal(rtmpUrl)
- expect(liveVideo.rtmpsUrl).to.equal(rtmpsUrl)
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl, streamKey: liveVideo.streamKey })
- await waitUntilLivePublishedOnAllServers([ server ], liveVideo.uuid)
- await stopFfmpeg(command)
- }
-
- {
- const liveVideo = await createLiveWrapper()
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpsUrl, streamKey: liveVideo.streamKey })
- await waitUntilLivePublishedOnAllServers([ server ], liveVideo.uuid)
- await stopFfmpeg(command)
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/live/live-save-replay.ts b/server/tests/api/live/live-save-replay.ts
deleted file mode 100644
index d554cf208..000000000
--- a/server/tests/api/live/live-save-replay.ts
+++ /dev/null
@@ -1,570 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { checkLiveCleanup } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, LiveVideoCreate, LiveVideoError, VideoPrivacy, VideoState } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createMultipleServers,
- doubleFollow,
- findExternalSavedVideo,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- testFfmpegStreamError,
- waitJobs,
- waitUntilLivePublishedOnAllServers,
- waitUntilLiveReplacedByReplayOnAllServers,
- waitUntilLiveWaitingOnAllServers
-} from '@shared/server-commands'
-
-describe('Save replay setting', function () {
- let servers: PeerTubeServer[] = []
- let liveVideoUUID: string
- let ffmpegCommand: FfmpegCommand
-
- async function createLiveWrapper (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacy } }) {
- if (liveVideoUUID) {
- try {
- await servers[0].videos.remove({ id: liveVideoUUID })
- await waitJobs(servers)
- } catch {}
- }
-
- const attributes: LiveVideoCreate = {
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- name: 'live'.repeat(30),
- saveReplay: options.replay,
- replaySettings: options.replaySettings,
- permanentLive: options.permanent
- }
-
- const { uuid } = await servers[0].live.create({ fields: attributes })
- return uuid
- }
-
- async function publishLive (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacy } }) {
- liveVideoUUID = await createLiveWrapper(options)
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
-
- const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
-
- await waitJobs(servers)
- await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
-
- return { ffmpegCommand, liveDetails }
- }
-
- async function publishLiveAndDelete (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacy } }) {
- const { ffmpegCommand, liveDetails } = await publishLive(options)
-
- await Promise.all([
- servers[0].videos.remove({ id: liveVideoUUID }),
- testFfmpegStreamError(ffmpegCommand, true)
- ])
-
- await waitJobs(servers)
- await wait(5000)
- await waitJobs(servers)
-
- return { liveDetails }
- }
-
- async function publishLiveAndBlacklist (options: { permanent: boolean, replay: boolean, replaySettings?: { privacy: VideoPrivacy } }) {
- const { ffmpegCommand, liveDetails } = await publishLive(options)
-
- await Promise.all([
- servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
- testFfmpegStreamError(ffmpegCommand, true)
- ])
-
- await waitJobs(servers)
- await wait(5000)
- await waitJobs(servers)
-
- return { liveDetails }
- }
-
- async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
- for (const server of servers) {
- const length = existsInList ? 1 : 0
-
- const { data, total } = await server.videos.list()
- expect(data).to.have.lengthOf(length)
- expect(total).to.equal(length)
-
- if (expectedStatus) {
- await server.videos.get({ id: videoId, expectedStatus })
- }
- }
- }
-
- async function checkVideoState (videoId: string, state: VideoState) {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoId })
- expect(video.state.id).to.equal(state)
- }
- }
-
- async function checkVideoPrivacy (videoId: string, privacy: VideoPrivacy) {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoId })
- expect(video.privacy.id).to.equal(privacy)
- }
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
- enabled: false,
- resolutions: ConfigCommand.getCustomConfigResolutions(true)
- }
- }
- }
- })
- })
-
- describe('With save replay disabled', function () {
- let sessionStartDateMin: Date
- let sessionStartDateMax: Date
- let sessionEndDateMin: Date
-
- it('Should correctly create and federate the "waiting for stream" live', async function () {
- this.timeout(40000)
-
- liveVideoUUID = await createLiveWrapper({ permanent: false, replay: false })
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
- })
-
- it('Should correctly have updated the live and federated it when streaming in the live', async function () {
- this.timeout(120000)
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
-
- sessionStartDateMin = new Date()
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
- sessionStartDateMax = new Date()
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
- })
-
- it('Should correctly delete the video files after the stream ended', async function () {
- this.timeout(120000)
-
- sessionEndDateMin = new Date()
- await stopFfmpeg(ffmpegCommand)
-
- for (const server of servers) {
- await server.live.waitUntilEnded({ videoId: liveVideoUUID })
- }
- await waitJobs(servers)
-
- // Live still exist, but cannot be played anymore
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
-
- // No resolutions saved since we did not save replay
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
-
- it('Should have appropriate ended session', async function () {
- const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const session = data[0]
-
- const startDate = new Date(session.startDate)
- expect(startDate).to.be.above(sessionStartDateMin)
- expect(startDate).to.be.below(sessionStartDateMax)
-
- expect(session.endDate).to.exist
- expect(new Date(session.endDate)).to.be.above(sessionEndDateMin)
-
- expect(session.saveReplay).to.be.false
- expect(session.error).to.not.exist
- expect(session.replayVideo).to.not.exist
- })
-
- it('Should correctly terminate the stream on blacklist and delete the live', async function () {
- this.timeout(120000)
-
- await publishLiveAndBlacklist({ permanent: false, replay: false })
-
- await checkVideosExist(liveVideoUUID, false)
-
- await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
-
- await wait(5000)
- await waitJobs(servers)
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
-
- it('Should have blacklisted session error', async function () {
- const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID })
- expect(session.startDate).to.exist
- expect(session.endDate).to.exist
-
- expect(session.error).to.equal(LiveVideoError.BLACKLISTED)
- expect(session.replayVideo).to.not.exist
- })
-
- it('Should correctly terminate the stream on delete and delete the video', async function () {
- this.timeout(120000)
-
- await publishLiveAndDelete({ permanent: false, replay: false })
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
- })
-
- describe('With save replay enabled on non permanent live', function () {
-
- it('Should correctly create and federate the "waiting for stream" live', async function () {
- this.timeout(120000)
-
- liveVideoUUID = await createLiveWrapper({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } })
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should correctly have updated the live and federated it when streaming in the live', async function () {
- this.timeout(120000)
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should correctly have saved the live and federated it after the streaming', async function () {
- this.timeout(120000)
-
- const session = await servers[0].live.findLatestSession({ videoId: liveVideoUUID })
- expect(session.endDate).to.not.exist
- expect(session.endingProcessed).to.be.false
- expect(session.saveReplay).to.be.true
- expect(session.replaySettings).to.exist
- expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- // Live has been transcoded
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.UNLISTED)
- })
-
- it('Should find the replay live session', async function () {
- const session = await servers[0].live.getReplaySession({ videoId: liveVideoUUID })
-
- expect(session).to.exist
-
- expect(session.startDate).to.exist
- expect(session.endDate).to.exist
-
- expect(session.error).to.not.exist
- expect(session.saveReplay).to.be.true
- expect(session.endingProcessed).to.be.true
- expect(session.replaySettings).to.exist
- expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
-
- expect(session.replayVideo).to.exist
- expect(session.replayVideo.id).to.exist
- expect(session.replayVideo.shortUUID).to.exist
- expect(session.replayVideo.uuid).to.equal(liveVideoUUID)
- })
-
- it('Should update the saved live and correctly federate the updated attributes', async function () {
- this.timeout(120000)
-
- await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated', privacy: VideoPrivacy.PUBLIC } })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: liveVideoUUID })
- expect(video.name).to.equal('video updated')
- expect(video.isLive).to.be.false
- expect(video.privacy.id).to.equal(VideoPrivacy.PUBLIC)
- }
- })
-
- it('Should have cleaned up the live files', async function () {
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] })
- })
-
- it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
- this.timeout(120000)
-
- await publishLiveAndBlacklist({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } })
-
- await checkVideosExist(liveVideoUUID, false)
-
- await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
-
- await wait(5000)
- await waitJobs(servers)
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false, savedResolutions: [ 720 ] })
- })
-
- it('Should correctly terminate the stream on delete and delete the video', async function () {
- this.timeout(120000)
-
- await publishLiveAndDelete({ permanent: false, replay: true, replaySettings: { privacy: VideoPrivacy.PUBLIC } })
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
- })
-
- describe('With save replay enabled on permanent live', function () {
- let lastReplayUUID: string
-
- describe('With a first live and its replay', function () {
-
- it('Should correctly create and federate the "waiting for stream" live', async function () {
- this.timeout(120000)
-
- liveVideoUUID = await createLiveWrapper({ permanent: true, replay: true, replaySettings: { privacy: VideoPrivacy.UNLISTED } })
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should correctly have updated the live and federated it when streaming in the live', async function () {
- this.timeout(120000)
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should correctly have saved the live and federated it after the streaming', async function () {
- this.timeout(120000)
-
- const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- const video = await findExternalSavedVideo(servers[0], liveDetails)
- expect(video).to.exist
-
- for (const server of servers) {
- await server.videos.get({ id: video.uuid })
- }
-
- lastReplayUUID = video.uuid
- })
-
- it('Should have appropriate ended session and replay live session', async function () {
- const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const sessionFromLive = data[0]
- const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID })
-
- for (const session of [ sessionFromLive, sessionFromReplay ]) {
- expect(session.startDate).to.exist
- expect(session.endDate).to.exist
-
- expect(session.replaySettings).to.exist
- expect(session.replaySettings.privacy).to.equal(VideoPrivacy.UNLISTED)
-
- expect(session.error).to.not.exist
-
- expect(session.replayVideo).to.exist
- expect(session.replayVideo.id).to.exist
- expect(session.replayVideo.shortUUID).to.exist
- expect(session.replayVideo.uuid).to.equal(lastReplayUUID)
- }
- })
-
- it('Should have the first live replay with correct settings', async function () {
- await checkVideosExist(lastReplayUUID, false, HttpStatusCode.OK_200)
- await checkVideoState(lastReplayUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.UNLISTED)
- })
- })
-
- describe('With a second live and its replay', function () {
-
- it('Should update the replay settings', async function () {
- await servers[0].live.update({ videoId: liveVideoUUID, fields: { replaySettings: { privacy: VideoPrivacy.PUBLIC } } })
- await waitJobs(servers)
-
- const live = await servers[0].live.get({ videoId: liveVideoUUID })
-
- expect(live.saveReplay).to.be.true
- expect(live.replaySettings).to.exist
- expect(live.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC)
-
- })
-
- it('Should correctly have updated the live and federated it when streaming in the live', async function () {
- this.timeout(120000)
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
-
- await waitJobs(servers)
-
- await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
- await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(liveVideoUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should correctly have saved the live and federated it after the streaming', async function () {
- this.timeout(120000)
-
- const liveDetails = await servers[0].videos.get({ id: liveVideoUUID })
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveWaitingOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- const video = await findExternalSavedVideo(servers[0], liveDetails)
- expect(video).to.exist
-
- for (const server of servers) {
- await server.videos.get({ id: video.uuid })
- }
-
- lastReplayUUID = video.uuid
- })
-
- it('Should have appropriate ended session and replay live session', async function () {
- const { data, total } = await servers[0].live.listSessions({ videoId: liveVideoUUID })
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- const sessionFromLive = data[1]
- const sessionFromReplay = await servers[0].live.getReplaySession({ videoId: lastReplayUUID })
-
- for (const session of [ sessionFromLive, sessionFromReplay ]) {
- expect(session.startDate).to.exist
- expect(session.endDate).to.exist
-
- expect(session.replaySettings).to.exist
- expect(session.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC)
-
- expect(session.error).to.not.exist
-
- expect(session.replayVideo).to.exist
- expect(session.replayVideo.id).to.exist
- expect(session.replayVideo.shortUUID).to.exist
- expect(session.replayVideo.uuid).to.equal(lastReplayUUID)
- }
- })
-
- it('Should have the first live replay with correct settings', async function () {
- await checkVideosExist(lastReplayUUID, true, HttpStatusCode.OK_200)
- await checkVideoState(lastReplayUUID, VideoState.PUBLISHED)
- await checkVideoPrivacy(lastReplayUUID, VideoPrivacy.PUBLIC)
- })
-
- it('Should have cleaned up the live files', async function () {
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
-
- it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
- this.timeout(120000)
-
- await servers[0].videos.remove({ id: lastReplayUUID })
- const { liveDetails } = await publishLiveAndBlacklist({
- permanent: true,
- replay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC }
- })
-
- const replay = await findExternalSavedVideo(servers[0], liveDetails)
- expect(replay).to.exist
-
- for (const videoId of [ liveVideoUUID, replay.uuid ]) {
- await checkVideosExist(videoId, false)
-
- await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await servers[1].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
-
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
-
- it('Should correctly terminate the stream on delete and not save the video', async function () {
- this.timeout(120000)
-
- const { liveDetails } = await publishLiveAndDelete({
- permanent: true,
- replay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC }
- })
-
- const replay = await findExternalSavedVideo(servers[0], liveDetails)
- expect(replay).to.not.exist
-
- await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
- await checkLiveCleanup({ server: servers[0], videoUUID: liveVideoUUID, permanent: false })
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/live/live-socket-messages.ts b/server/tests/api/live/live-socket-messages.ts
deleted file mode 100644
index 0cccd1594..000000000
--- a/server/tests/api/live/live-socket-messages.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { LiveVideoEventPayload, VideoPrivacy, VideoState } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs,
- waitUntilLivePublishedOnAllServers
-} from '@shared/server-commands'
-
-describe('Test live socket messages', function () {
- let servers: PeerTubeServer[] = []
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
- }
- }
- }
- })
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Live socket messages', function () {
-
- async function createLiveWrapper () {
- const liveAttributes = {
- name: 'live video',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
-
- const { uuid } = await servers[0].live.create({ fields: liveAttributes })
- return uuid
- }
-
- it('Should correctly send a message when the live starts and ends', async function () {
- this.timeout(60000)
-
- const localStateChanges: VideoState[] = []
- const remoteStateChanges: VideoState[] = []
-
- const liveVideoUUID = await createLiveWrapper()
- await waitJobs(servers)
-
- {
- const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
-
- const localSocket = servers[0].socketIO.getLiveNotificationSocket()
- localSocket.on('state-change', data => localStateChanges.push(data.state))
- localSocket.emit('subscribe', { videoId })
- }
-
- {
- const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
-
- const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
- remoteSocket.on('state-change', data => remoteStateChanges.push(data.state))
- remoteSocket.emit('subscribe', { videoId })
- }
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
- expect(stateChanges).to.have.length.at.least(1)
- expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
- }
-
- await stopFfmpeg(ffmpegCommand)
-
- for (const server of servers) {
- await server.live.waitUntilEnded({ videoId: liveVideoUUID })
- }
- await waitJobs(servers)
-
- for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
- expect(stateChanges).to.have.length.at.least(2)
- expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.LIVE_ENDED)
- }
- })
-
- it('Should correctly send views change notification', async function () {
- this.timeout(60000)
-
- let localLastVideoViews = 0
- let remoteLastVideoViews = 0
-
- const liveVideoUUID = await createLiveWrapper()
- await waitJobs(servers)
-
- {
- const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
-
- const localSocket = servers[0].socketIO.getLiveNotificationSocket()
- localSocket.on('views-change', (data: LiveVideoEventPayload) => { localLastVideoViews = data.viewers })
- localSocket.emit('subscribe', { videoId })
- }
-
- {
- const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
-
- const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
- remoteSocket.on('views-change', (data: LiveVideoEventPayload) => { remoteLastVideoViews = data.viewers })
- remoteSocket.emit('subscribe', { videoId })
- }
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- expect(localLastVideoViews).to.equal(0)
- expect(remoteLastVideoViews).to.equal(0)
-
- await servers[0].views.simulateView({ id: liveVideoUUID })
- await servers[1].views.simulateView({ id: liveVideoUUID })
-
- await waitJobs(servers)
-
- expect(localLastVideoViews).to.equal(2)
- expect(remoteLastVideoViews).to.equal(2)
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should not receive a notification after unsubscribe', async function () {
- this.timeout(120000)
-
- const stateChanges: VideoState[] = []
-
- const liveVideoUUID = await createLiveWrapper()
- await waitJobs(servers)
-
- const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
-
- const socket = servers[0].socketIO.getLiveNotificationSocket()
- socket.on('state-change', data => stateChanges.push(data.state))
- socket.emit('subscribe', { videoId })
-
- const command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
- await waitJobs(servers)
-
- // Notifier waits before sending a notification
- await wait(10000)
-
- expect(stateChanges).to.have.lengthOf(1)
- socket.emit('unsubscribe', { videoId })
-
- await stopFfmpeg(command)
- await waitJobs(servers)
-
- expect(stateChanges).to.have.lengthOf(1)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
deleted file mode 100644
index 2b302a8a2..000000000
--- a/server/tests/api/live/live.ts
+++ /dev/null
@@ -1,764 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { basename, join } from 'path'
-import { SQLCommand, testImageGeneratedByFFmpeg, testLiveVideoResolutions } from '@server/tests/shared'
-import { getAllFiles, wait } from '@shared/core-utils'
-import { ffprobePromise, getVideoStream } from '@shared/ffmpeg'
-import {
- HttpStatusCode,
- LiveVideo,
- LiveVideoCreate,
- LiveVideoLatencyMode,
- VideoDetails,
- VideoPrivacy,
- VideoState,
- VideoStreamingPlaylistType
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- LiveCommand,
- makeGetRequest,
- makeRawRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- testFfmpegStreamError,
- waitJobs,
- waitUntilLivePublishedOnAllServers
-} from '@shared/server-commands'
-
-describe('Test live', function () {
- let servers: PeerTubeServer[] = []
- let commands: LiveCommand[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- latencySetting: {
- enabled: true
- },
- transcoding: {
- enabled: false
- }
- }
- }
- })
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- commands = servers.map(s => s.live)
- })
-
- describe('Live creation, update and delete', function () {
- let liveVideoUUID: string
-
- it('Should create a live with the appropriate parameters', async function () {
- this.timeout(20000)
-
- const attributes: LiveVideoCreate = {
- category: 1,
- licence: 2,
- language: 'fr',
- description: 'super live description',
- support: 'support field',
- channelId: servers[0].store.channel.id,
- nsfw: false,
- waitTranscoding: false,
- name: 'my super live',
- tags: [ 'tag1', 'tag2' ],
- commentsEnabled: false,
- downloadEnabled: false,
- saveReplay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC },
- latencyMode: LiveVideoLatencyMode.SMALL_LATENCY,
- privacy: VideoPrivacy.PUBLIC,
- previewfile: 'video_short1-preview.webm.jpg',
- thumbnailfile: 'video_short1.webm.jpg'
- }
-
- const live = await commands[0].create({ fields: attributes })
- liveVideoUUID = live.uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: liveVideoUUID })
-
- expect(video.category.id).to.equal(1)
- expect(video.licence.id).to.equal(2)
- expect(video.language.id).to.equal('fr')
- expect(video.description).to.equal('super live description')
- expect(video.support).to.equal('support field')
-
- expect(video.channel.name).to.equal(servers[0].store.channel.name)
- expect(video.channel.host).to.equal(servers[0].store.channel.host)
-
- expect(video.isLive).to.be.true
-
- expect(video.nsfw).to.be.false
- expect(video.waitTranscoding).to.be.false
- expect(video.name).to.equal('my super live')
- expect(video.tags).to.deep.equal([ 'tag1', 'tag2' ])
- expect(video.commentsEnabled).to.be.false
- expect(video.downloadEnabled).to.be.false
- expect(video.privacy.id).to.equal(VideoPrivacy.PUBLIC)
-
- await testImageGeneratedByFFmpeg(server.url, 'video_short1-preview.webm', video.previewPath)
- await testImageGeneratedByFFmpeg(server.url, 'video_short1.webm', video.thumbnailPath)
-
- const live = await server.live.get({ videoId: liveVideoUUID })
-
- if (server.url === servers[0].url) {
- expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
- expect(live.streamKey).to.not.be.empty
-
- expect(live.replaySettings).to.exist
- expect(live.replaySettings.privacy).to.equal(VideoPrivacy.PUBLIC)
- } else {
- expect(live.rtmpUrl).to.not.exist
- expect(live.streamKey).to.not.exist
- }
-
- expect(live.saveReplay).to.be.true
- expect(live.latencyMode).to.equal(LiveVideoLatencyMode.SMALL_LATENCY)
- }
- })
-
- it('Should have a default preview and thumbnail', async function () {
- this.timeout(20000)
-
- const attributes: LiveVideoCreate = {
- name: 'default live thumbnail',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.UNLISTED,
- nsfw: true
- }
-
- const live = await commands[0].create({ fields: attributes })
- const videoId = live.uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoId })
- expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
- expect(video.nsfw).to.be.true
-
- await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should not have the live listed since nobody streams into', async function () {
- for (const server of servers) {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
- })
-
- it('Should not be able to update a live of another server', async function () {
- await commands[1].update({ videoId: liveVideoUUID, fields: { saveReplay: false }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should update the live', async function () {
- await commands[0].update({ videoId: liveVideoUUID, fields: { saveReplay: false, latencyMode: LiveVideoLatencyMode.DEFAULT } })
- await waitJobs(servers)
- })
-
- it('Have the live updated', async function () {
- for (const server of servers) {
- const live = await server.live.get({ videoId: liveVideoUUID })
-
- if (server.url === servers[0].url) {
- expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
- expect(live.streamKey).to.not.be.empty
- } else {
- expect(live.rtmpUrl).to.not.exist
- expect(live.streamKey).to.not.exist
- }
-
- expect(live.saveReplay).to.be.false
- expect(live.replaySettings).to.not.exist
- expect(live.latencyMode).to.equal(LiveVideoLatencyMode.DEFAULT)
- }
- })
-
- it('Delete the live', async function () {
- await servers[0].videos.remove({ id: liveVideoUUID })
- await waitJobs(servers)
- })
-
- it('Should have the live deleted', async function () {
- for (const server of servers) {
- await server.videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await server.live.get({ videoId: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
- })
-
- describe('Live filters', function () {
- let ffmpegCommand: any
- let liveVideoId: string
- let vodVideoId: string
-
- before(async function () {
- this.timeout(240000)
-
- vodVideoId = (await servers[0].videos.quickUpload({ name: 'vod video' })).uuid
-
- const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].store.channel.id }
- const live = await commands[0].create({ fields: liveOptions })
- liveVideoId = live.uuid
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
- })
-
- it('Should only display lives', async function () {
- const { data, total } = await servers[0].videos.list({ isLive: true })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('live')
- })
-
- it('Should not display lives', async function () {
- const { data, total } = await servers[0].videos.list({ isLive: false })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('vod video')
- })
-
- it('Should display my lives', async function () {
- this.timeout(60000)
-
- await stopFfmpeg(ffmpegCommand)
- await waitJobs(servers)
-
- const { data } = await servers[0].videos.listMyVideos({ isLive: true })
-
- const result = data.every(v => v.isLive)
- expect(result).to.be.true
- })
-
- it('Should not display my lives', async function () {
- const { data } = await servers[0].videos.listMyVideos({ isLive: false })
-
- const result = data.every(v => !v.isLive)
- expect(result).to.be.true
- })
-
- after(async function () {
- await servers[0].videos.remove({ id: vodVideoId })
- await servers[0].videos.remove({ id: liveVideoId })
- })
- })
-
- describe('Stream checks', function () {
- let liveVideo: LiveVideo & VideoDetails
- let rtmpUrl: string
-
- before(function () {
- rtmpUrl = 'rtmp://' + servers[0].hostname + ':' + servers[0].rtmpPort + ''
- })
-
- async function createLiveWrapper () {
- const liveAttributes = {
- name: 'user live',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- saveReplay: false
- }
-
- const { uuid } = await commands[0].create({ fields: liveAttributes })
-
- const live = await commands[0].get({ videoId: uuid })
- const video = await servers[0].videos.get({ id: uuid })
-
- return Object.assign(video, live)
- }
-
- it('Should not allow a stream without the appropriate path', async function () {
- this.timeout(60000)
-
- liveVideo = await createLiveWrapper()
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl + '/bad-live', streamKey: liveVideo.streamKey })
- await testFfmpegStreamError(command, true)
- })
-
- it('Should not allow a stream without the appropriate stream key', async function () {
- this.timeout(60000)
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl + '/live', streamKey: 'bad-stream-key' })
- await testFfmpegStreamError(command, true)
- })
-
- it('Should succeed with the correct params', async function () {
- this.timeout(60000)
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl + '/live', streamKey: liveVideo.streamKey })
- await testFfmpegStreamError(command, false)
- })
-
- it('Should list this live now someone stream into it', async function () {
- for (const server of servers) {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const video = data[0]
- expect(video.name).to.equal('user live')
- expect(video.isLive).to.be.true
- }
- })
-
- it('Should not allow a stream on a live that was blacklisted', async function () {
- this.timeout(60000)
-
- liveVideo = await createLiveWrapper()
-
- await servers[0].blacklist.add({ videoId: liveVideo.uuid })
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl + '/live', streamKey: liveVideo.streamKey })
- await testFfmpegStreamError(command, true)
- })
-
- it('Should not allow a stream on a live that was deleted', async function () {
- this.timeout(60000)
-
- liveVideo = await createLiveWrapper()
-
- await servers[0].videos.remove({ id: liveVideo.uuid })
-
- const command = sendRTMPStream({ rtmpBaseUrl: rtmpUrl + '/live', streamKey: liveVideo.streamKey })
- await testFfmpegStreamError(command, true)
- })
- })
-
- describe('Live transcoding', function () {
- let liveVideoId: string
- let sqlCommandServer1: SQLCommand
-
- async function createLiveWrapper (saveReplay: boolean) {
- const liveAttributes = {
- name: 'live video',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- saveReplay,
- replaySettings: saveReplay
- ? { privacy: VideoPrivacy.PUBLIC }
- : undefined
- }
-
- const { uuid } = await commands[0].create({ fields: liveAttributes })
- return uuid
- }
-
- function updateConf (resolutions: number[]) {
- return servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- maxDuration: -1,
- transcoding: {
- enabled: true,
- resolutions: {
- '144p': resolutions.includes(144),
- '240p': resolutions.includes(240),
- '360p': resolutions.includes(360),
- '480p': resolutions.includes(480),
- '720p': resolutions.includes(720),
- '1080p': resolutions.includes(1080),
- '2160p': resolutions.includes(2160)
- }
- }
- }
- }
- })
- }
-
- before(async function () {
- await updateConf([])
-
- sqlCommandServer1 = new SQLCommand(servers[0])
- })
-
- it('Should enable transcoding without additional resolutions', async function () {
- this.timeout(120000)
-
- liveVideoId = await createLiveWrapper(false)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId,
- resolutions: [ 720 ],
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should transcode audio only RTMP stream', async function () {
- this.timeout(120000)
-
- liveVideoId = await createLiveWrapper(false)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short_no_audio.mp4' })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should enable transcoding with some resolutions', async function () {
- this.timeout(240000)
-
- const resolutions = [ 240, 480 ]
- await updateConf(resolutions)
- liveVideoId = await createLiveWrapper(false)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId,
- resolutions: resolutions.concat([ 720 ]),
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should correctly set the appropriate bitrate depending on the input', async function () {
- this.timeout(120000)
-
- liveVideoId = await createLiveWrapper(false)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({
- videoId: liveVideoId,
- fixtureName: 'video_short.mp4',
- copyCodecs: true
- })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: liveVideoId })
-
- const masterPlaylist = video.streamingPlaylists[0].playlistUrl
- const probe = await ffprobePromise(masterPlaylist)
-
- const bitrates = probe.streams.map(s => parseInt(s.tags.variant_bitrate))
- for (const bitrate of bitrates) {
- expect(bitrate).to.exist
- expect(isNaN(bitrate)).to.be.false
- expect(bitrate).to.be.below(61_000_000) // video_short.mp4 bitrate
- }
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should enable transcoding with some resolutions and correctly save them', async function () {
- this.timeout(500_000)
-
- const resolutions = [ 240, 360, 720 ]
-
- await updateConf(resolutions)
- liveVideoId = await createLiveWrapper(true)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId,
- resolutions,
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- await commands[0].waitUntilEnded({ videoId: liveVideoId })
-
- await waitJobs(servers)
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
-
- const maxBitrateLimits = {
- 720: 6500 * 1000, // 60FPS
- 360: 1250 * 1000,
- 240: 700 * 1000
- }
-
- const minBitrateLimits = {
- 720: 4800 * 1000,
- 360: 1000 * 1000,
- 240: 550 * 1000
- }
-
- for (const server of servers) {
- const video = await server.videos.get({ id: liveVideoId })
-
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
- expect(video.duration).to.be.greaterThan(1)
- expect(video.files).to.have.lengthOf(0)
-
- const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
- await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
-
- // We should have generated random filenames
- expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8')
- expect(basename(hlsPlaylist.segmentsSha256Url)).to.not.equal('segments-sha256.json')
-
- expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
-
- for (const resolution of resolutions) {
- const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
-
- expect(file).to.exist
- expect(file.size).to.be.greaterThan(1)
-
- if (resolution >= 720) {
- expect(file.fps).to.be.approximately(60, 10)
- } else {
- expect(file.fps).to.be.approximately(30, 3)
- }
-
- const filename = basename(file.fileUrl)
- expect(filename).to.not.contain(video.uuid)
-
- const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename))
-
- const probe = await ffprobePromise(segmentPath)
- const videoStream = await getVideoStream(segmentPath, probe)
-
- expect(probe.format.bit_rate).to.be.below(maxBitrateLimits[videoStream.height])
- expect(probe.format.bit_rate).to.be.at.least(minBitrateLimits[videoStream.height])
-
- await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
-
- it('Should not generate an upper resolution than original file', async function () {
- this.timeout(500_000)
-
- const resolutions = [ 240, 480 ]
- await updateConf(resolutions)
-
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- live: {
- transcoding: {
- alwaysTranscodeOriginalResolution: false
- }
- }
- }
- })
-
- liveVideoId = await createLiveWrapper(true)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId,
- resolutions,
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- await commands[0].waitUntilEnded({ videoId: liveVideoId })
-
- await waitJobs(servers)
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
-
- const video = await servers[0].videos.get({ id: liveVideoId })
- const hlsFiles = video.streamingPlaylists[0].files
-
- expect(video.files).to.have.lengthOf(0)
- expect(hlsFiles).to.have.lengthOf(resolutions.length)
-
- // eslint-disable-next-line @typescript-eslint/require-array-sort-compare
- expect(getAllFiles(video).map(f => f.resolution.id).sort()).to.deep.equal(resolutions)
- })
-
- it('Should only keep the original resolution if all resolutions are disabled', async function () {
- this.timeout(600_000)
-
- await updateConf([])
- liveVideoId = await createLiveWrapper(true)
-
- const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId,
- resolutions: [ 720 ],
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- await commands[0].waitUntilEnded({ videoId: liveVideoId })
-
- await waitJobs(servers)
-
- await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
-
- const video = await servers[0].videos.get({ id: liveVideoId })
- const hlsFiles = video.streamingPlaylists[0].files
-
- expect(video.files).to.have.lengthOf(0)
- expect(hlsFiles).to.have.lengthOf(1)
-
- expect(hlsFiles[0].resolution.id).to.equal(720)
- })
-
- after(async function () {
- await sqlCommandServer1.cleanup()
- })
- })
-
- describe('After a server restart', function () {
- let liveVideoId: string
- let liveVideoReplayId: string
- let permanentLiveVideoReplayId: string
-
- let permanentLiveReplayName: string
-
- let beforeServerRestart: Date
-
- async function createLiveWrapper (options: { saveReplay: boolean, permanent: boolean }) {
- const liveAttributes: LiveVideoCreate = {
- name: 'live video',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- saveReplay: options.saveReplay,
- replaySettings: options.saveReplay
- ? { privacy: VideoPrivacy.PUBLIC }
- : undefined,
- permanentLive: options.permanent
- }
-
- const { uuid } = await commands[0].create({ fields: liveAttributes })
- return uuid
- }
-
- before(async function () {
- this.timeout(600_000)
-
- liveVideoId = await createLiveWrapper({ saveReplay: false, permanent: false })
- liveVideoReplayId = await createLiveWrapper({ saveReplay: true, permanent: false })
- permanentLiveVideoReplayId = await createLiveWrapper({ saveReplay: true, permanent: true })
-
- await Promise.all([
- commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }),
- commands[0].sendRTMPStreamInVideo({ videoId: permanentLiveVideoReplayId }),
- commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId })
- ])
-
- await Promise.all([
- commands[0].waitUntilPublished({ videoId: liveVideoId }),
- commands[0].waitUntilPublished({ videoId: permanentLiveVideoReplayId }),
- commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
- ])
-
- for (const videoUUID of [ liveVideoId, liveVideoReplayId, permanentLiveVideoReplayId ]) {
- await commands[0].waitUntilSegmentGeneration({
- server: servers[0],
- videoUUID,
- playlistNumber: 0,
- segment: 2
- })
- }
-
- {
- const video = await servers[0].videos.get({ id: permanentLiveVideoReplayId })
- permanentLiveReplayName = video.name + ' - ' + new Date(video.publishedAt).toLocaleString()
- }
-
- await killallServers([ servers[0] ])
-
- beforeServerRestart = new Date()
- await servers[0].run()
-
- await wait(5000)
- await waitJobs(servers)
- })
-
- it('Should cleanup lives', async function () {
- this.timeout(60000)
-
- await commands[0].waitUntilEnded({ videoId: liveVideoId })
- await commands[0].waitUntilWaiting({ videoId: permanentLiveVideoReplayId })
- })
-
- it('Should save a non permanent live replay', async function () {
- this.timeout(240000)
-
- await commands[0].waitUntilPublished({ videoId: liveVideoReplayId })
-
- const session = await commands[0].getReplaySession({ videoId: liveVideoReplayId })
- expect(session.endDate).to.exist
- expect(new Date(session.endDate)).to.be.above(beforeServerRestart)
- })
-
- it('Should have saved a permanent live replay', async function () {
- this.timeout(120000)
-
- const { data } = await servers[0].videos.listMyVideos({ sort: '-publishedAt' })
- expect(data.find(v => v.name === permanentLiveReplayName)).to.exist
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts
deleted file mode 100644
index 9fc296ea8..000000000
--- a/server/tests/api/moderation/abuses.ts
+++ /dev/null
@@ -1,887 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { AbuseMessage, AbusePredefinedReasonsString, AbuseState, AdminAbuse, UserAbuse } from '@shared/models'
-import {
- AbusesCommand,
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test abuses', function () {
- let servers: PeerTubeServer[] = []
- let abuseServer1: AdminAbuse
- let abuseServer2: AdminAbuse
- let commands: AbusesCommand[]
-
- before(async function () {
- this.timeout(50000)
-
- // Run servers
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultChannelAvatar(servers)
- await setDefaultAccountAvatar(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- commands = servers.map(s => s.abuses)
- })
-
- describe('Video abuses', function () {
-
- before(async function () {
- this.timeout(50000)
-
- // Upload some videos on each servers
- {
- const attributes = {
- name: 'my super name for server 1',
- description: 'my super description for server 1'
- }
- await servers[0].videos.upload({ attributes })
- }
-
- {
- const attributes = {
- name: 'my super name for server 2',
- description: 'my super description for server 2'
- }
- await servers[1].videos.upload({ attributes })
- }
-
- // Wait videos propagation, server 2 has transcoding enabled
- await waitJobs(servers)
-
- const { data } = await servers[0].videos.list()
- expect(data.length).to.equal(2)
-
- servers[0].store.videoCreated = data.find(video => video.name === 'my super name for server 1')
- servers[1].store.videoCreated = data.find(video => video.name === 'my super name for server 2')
- })
-
- it('Should not have abuses', async function () {
- const body = await commands[0].getAdminList()
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- })
-
- it('Should report abuse on a local video', async function () {
- this.timeout(15000)
-
- const reason = 'my super bad reason'
- await commands[0].report({ videoId: servers[0].store.videoCreated.id, reason })
-
- // We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
- await waitJobs(servers)
- })
-
- it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
- {
- const body = await commands[0].getAdminList()
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
-
- const abuse = body.data[0]
- expect(abuse.reason).to.equal('my super bad reason')
-
- expect(abuse.reporterAccount.name).to.equal('root')
- expect(abuse.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse.video.id).to.equal(servers[0].store.videoCreated.id)
- expect(abuse.video.channel).to.exist
-
- expect(abuse.comment).to.be.null
-
- expect(abuse.flaggedAccount.name).to.equal('root')
- expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
-
- expect(abuse.video.countReports).to.equal(1)
- expect(abuse.video.nthReport).to.equal(1)
-
- expect(abuse.countReportsForReporter).to.equal(1)
- expect(abuse.countReportsForReportee).to.equal(1)
- }
-
- {
- const body = await commands[1].getAdminList()
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
- })
-
- it('Should report abuse on a remote video', async function () {
- const reason = 'my super bad reason 2'
- const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
- await commands[0].report({ videoId, reason })
-
- // We wait requests propagation
- await waitJobs(servers)
- })
-
- it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
- {
- const body = await commands[0].getAdminList()
-
- expect(body.total).to.equal(2)
- expect(body.data.length).to.equal(2)
-
- const abuse1 = body.data[0]
- expect(abuse1.reason).to.equal('my super bad reason')
- expect(abuse1.reporterAccount.name).to.equal('root')
- expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse1.video.id).to.equal(servers[0].store.videoCreated.id)
- expect(abuse1.video.countReports).to.equal(1)
- expect(abuse1.video.nthReport).to.equal(1)
-
- expect(abuse1.comment).to.be.null
-
- expect(abuse1.flaggedAccount.name).to.equal('root')
- expect(abuse1.flaggedAccount.host).to.equal(servers[0].host)
-
- expect(abuse1.state.id).to.equal(AbuseState.PENDING)
- expect(abuse1.state.label).to.equal('Pending')
- expect(abuse1.moderationComment).to.be.null
-
- const abuse2 = body.data[1]
- expect(abuse2.reason).to.equal('my super bad reason 2')
-
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse2.video.uuid).to.equal(servers[1].store.videoCreated.uuid)
-
- expect(abuse2.comment).to.be.null
-
- expect(abuse2.flaggedAccount.name).to.equal('root')
- expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
-
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
- expect(abuse2.moderationComment).to.be.null
- }
-
- {
- const body = await commands[1].getAdminList()
- expect(body.total).to.equal(1)
- expect(body.data.length).to.equal(1)
-
- abuseServer2 = body.data[0]
- expect(abuseServer2.reason).to.equal('my super bad reason 2')
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuseServer2.flaggedAccount.name).to.equal('root')
- expect(abuseServer2.flaggedAccount.host).to.equal(servers[1].host)
-
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
- expect(abuseServer2.moderationComment).to.be.null
- }
- })
-
- it('Should hide video abuses from blocked accounts', async function () {
- {
- const videoId = await servers[1].videos.getId({ uuid: servers[0].store.videoCreated.uuid })
- await commands[1].report({ videoId, reason: 'will mute this' })
- await waitJobs(servers)
-
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(3)
- }
-
- const accountToBlock = 'root@' + servers[1].host
-
- {
- await servers[0].blocklist.addToServerBlocklist({ account: accountToBlock })
-
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(2)
-
- const abuse = body.data.find(a => a.reason === 'will mute this')
- expect(abuse).to.be.undefined
- }
-
- {
- await servers[0].blocklist.removeFromServerBlocklist({ account: accountToBlock })
-
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(3)
- }
- })
-
- it('Should hide video abuses from blocked servers', async function () {
- const serverToBlock = servers[1].host
-
- {
- await servers[0].blocklist.addToServerBlocklist({ server: serverToBlock })
-
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(2)
-
- const abuse = body.data.find(a => a.reason === 'will mute this')
- expect(abuse).to.be.undefined
- }
-
- {
- await servers[0].blocklist.removeFromServerBlocklist({ server: serverToBlock })
-
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(3)
- }
- })
-
- it('Should keep the video abuse when deleting the video', async function () {
- await servers[1].videos.remove({ id: abuseServer2.video.uuid })
-
- await waitJobs(servers)
-
- const body = await commands[1].getAdminList()
- expect(body.total).to.equal(2, 'wrong number of videos returned')
- expect(body.data).to.have.lengthOf(2, 'wrong number of videos returned')
-
- const abuse = body.data[0]
- expect(abuse.id).to.equal(abuseServer2.id, 'wrong origin server id for first video')
- expect(abuse.video.id).to.equal(abuseServer2.video.id, 'wrong video id')
- expect(abuse.video.channel).to.exist
- expect(abuse.video.deleted).to.be.true
- })
-
- it('Should include counts of reports from reporter and reportee', async function () {
- // register a second user to have two reporters/reportees
- const user = { username: 'user2', password: 'password' }
- await servers[0].users.create({ ...user })
- const userAccessToken = await servers[0].login.getAccessToken(user)
-
- // upload a third video via this user
- const attributes = {
- name: 'my second super name for server 1',
- description: 'my second super description for server 1'
- }
- const { id } = await servers[0].videos.upload({ token: userAccessToken, attributes })
- const video3Id = id
-
- // resume with the test
- const reason3 = 'my super bad reason 3'
- await commands[0].report({ videoId: video3Id, reason: reason3 })
-
- const reason4 = 'my super bad reason 4'
- await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: reason4 })
-
- {
- const body = await commands[0].getAdminList()
- const abuses = body.data
-
- const abuseVideo3 = body.data.find(a => a.video.id === video3Id)
- expect(abuseVideo3).to.not.be.undefined
- expect(abuseVideo3.video.countReports).to.equal(1, 'wrong reports count for video 3')
- expect(abuseVideo3.video.nthReport).to.equal(1, 'wrong report position in report list for video 3')
- expect(abuseVideo3.countReportsForReportee).to.equal(1, 'wrong reports count for reporter on video 3 abuse')
- expect(abuseVideo3.countReportsForReporter).to.equal(3, 'wrong reports count for reportee on video 3 abuse')
-
- const abuseServer1 = abuses.find(a => a.video.id === servers[0].store.videoCreated.id)
- expect(abuseServer1.countReportsForReportee).to.equal(3, 'wrong reports count for reporter on video 1 abuse')
- }
- })
-
- it('Should list predefined reasons as well as timestamps for the reported video', async function () {
- const reason5 = 'my super bad reason 5'
- const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
- const createRes = await commands[0].report({
- videoId: servers[0].store.videoCreated.id,
- reason: reason5,
- predefinedReasons: predefinedReasons5,
- startAt: 1,
- endAt: 5
- })
-
- const body = await commands[0].getAdminList()
-
- {
- const abuse = body.data.find(a => a.id === createRes.abuse.id)
- expect(abuse.reason).to.equals(reason5)
- expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, 'predefined reasons do not match the one reported')
- expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported")
- expect(abuse.video.endAt).to.equal(5, "ending timestamp doesn't match the one reported")
- }
- })
-
- it('Should delete the video abuse', async function () {
- await commands[1].delete({ abuseId: abuseServer2.id })
-
- await waitJobs(servers)
-
- {
- const body = await commands[1].getAdminList()
- expect(body.total).to.equal(1)
- expect(body.data.length).to.equal(1)
- expect(body.data[0].id).to.not.equal(abuseServer2.id)
- }
-
- {
- const body = await commands[0].getAdminList()
- expect(body.total).to.equal(6)
- }
- })
-
- it('Should list and filter video abuses', async function () {
- async function list (query: Parameters[0]) {
- const body = await commands[0].getAdminList(query)
-
- return body.data
- }
-
- expect(await list({ id: 56 })).to.have.lengthOf(0)
- expect(await list({ id: 1 })).to.have.lengthOf(1)
-
- expect(await list({ search: 'my super name for server 1' })).to.have.lengthOf(4)
- expect(await list({ search: 'aaaaaaaaaaaaaaaaaaaaaaaaaa' })).to.have.lengthOf(0)
-
- expect(await list({ searchVideo: 'my second super name for server 1' })).to.have.lengthOf(1)
-
- expect(await list({ searchVideoChannel: 'root' })).to.have.lengthOf(4)
- expect(await list({ searchVideoChannel: 'aaaa' })).to.have.lengthOf(0)
-
- expect(await list({ searchReporter: 'user2' })).to.have.lengthOf(1)
- expect(await list({ searchReporter: 'root' })).to.have.lengthOf(5)
-
- expect(await list({ searchReportee: 'root' })).to.have.lengthOf(5)
- expect(await list({ searchReportee: 'aaaa' })).to.have.lengthOf(0)
-
- expect(await list({ videoIs: 'deleted' })).to.have.lengthOf(1)
- expect(await list({ videoIs: 'blacklisted' })).to.have.lengthOf(0)
-
- expect(await list({ state: AbuseState.ACCEPTED })).to.have.lengthOf(0)
- expect(await list({ state: AbuseState.PENDING })).to.have.lengthOf(6)
-
- expect(await list({ predefinedReason: 'violentOrRepulsive' })).to.have.lengthOf(1)
- expect(await list({ predefinedReason: 'serverRules' })).to.have.lengthOf(0)
- })
- })
-
- describe('Comment abuses', function () {
-
- async function getComment (server: PeerTubeServer, videoIdArg: number | string) {
- const videoId = typeof videoIdArg === 'string'
- ? await server.videos.getId({ uuid: videoIdArg })
- : videoIdArg
-
- const { data } = await server.comments.listThreads({ videoId })
-
- return data[0]
- }
-
- before(async function () {
- this.timeout(50000)
-
- servers[0].store.videoCreated = await servers[0].videos.quickUpload({ name: 'server 1' })
- servers[1].store.videoCreated = await servers[1].videos.quickUpload({ name: 'server 2' })
-
- await servers[0].comments.createThread({ videoId: servers[0].store.videoCreated.id, text: 'comment server 1' })
- await servers[1].comments.createThread({ videoId: servers[1].store.videoCreated.id, text: 'comment server 2' })
-
- await waitJobs(servers)
- })
-
- it('Should report abuse on a comment', async function () {
- this.timeout(15000)
-
- const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
-
- const reason = 'it is a bad comment'
- await commands[0].report({ commentId: comment.id, reason })
-
- await waitJobs(servers)
- })
-
- it('Should have 1 comment abuse on server 1 and 0 on server 2', async function () {
- {
- const comment = await getComment(servers[0], servers[0].store.videoCreated.id)
- const body = await commands[0].getAdminList({ filter: 'comment' })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const abuse = body.data[0]
- expect(abuse.reason).to.equal('it is a bad comment')
-
- expect(abuse.reporterAccount.name).to.equal('root')
- expect(abuse.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse.video).to.be.null
-
- expect(abuse.comment.deleted).to.be.false
- expect(abuse.comment.id).to.equal(comment.id)
- expect(abuse.comment.text).to.equal(comment.text)
- expect(abuse.comment.video.name).to.equal('server 1')
- expect(abuse.comment.video.id).to.equal(servers[0].store.videoCreated.id)
- expect(abuse.comment.video.uuid).to.equal(servers[0].store.videoCreated.uuid)
-
- expect(abuse.countReportsForReporter).to.equal(5)
- expect(abuse.countReportsForReportee).to.equal(5)
- }
-
- {
- const body = await commands[1].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(0)
- expect(body.data.length).to.equal(0)
- }
- })
-
- it('Should report abuse on a remote comment', async function () {
- const comment = await getComment(servers[0], servers[1].store.videoCreated.uuid)
-
- const reason = 'it is a really bad comment'
- await commands[0].report({ commentId: comment.id, reason })
-
- await waitJobs(servers)
- })
-
- it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
- const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.shortUUID)
-
- {
- const body = await commands[0].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(2)
- expect(body.data.length).to.equal(2)
-
- const abuse = body.data[0]
- expect(abuse.reason).to.equal('it is a bad comment')
- expect(abuse.countReportsForReporter).to.equal(6)
- expect(abuse.countReportsForReportee).to.equal(5)
-
- const abuse2 = body.data[1]
-
- expect(abuse2.reason).to.equal('it is a really bad comment')
-
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse2.video).to.be.null
-
- expect(abuse2.comment.deleted).to.be.false
- expect(abuse2.comment.id).to.equal(commentServer2.id)
- expect(abuse2.comment.text).to.equal(commentServer2.text)
- expect(abuse2.comment.video.name).to.equal('server 2')
- expect(abuse2.comment.video.uuid).to.equal(servers[1].store.videoCreated.uuid)
-
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
-
- expect(abuse2.moderationComment).to.be.null
-
- expect(abuse2.countReportsForReporter).to.equal(6)
- expect(abuse2.countReportsForReportee).to.equal(2)
- }
-
- {
- const body = await commands[1].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(1)
- expect(body.data.length).to.equal(1)
-
- abuseServer2 = body.data[0]
- expect(abuseServer2.reason).to.equal('it is a really bad comment')
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
-
- expect(abuseServer2.moderationComment).to.be.null
-
- expect(abuseServer2.countReportsForReporter).to.equal(1)
- expect(abuseServer2.countReportsForReportee).to.equal(1)
- }
- })
-
- it('Should keep the comment abuse when deleting the comment', async function () {
- const commentServer2 = await getComment(servers[0], servers[1].store.videoCreated.uuid)
-
- await servers[0].comments.delete({ videoId: servers[1].store.videoCreated.uuid, commentId: commentServer2.id })
-
- await waitJobs(servers)
-
- const body = await commands[0].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- const abuse = body.data.find(a => a.comment?.id === commentServer2.id)
- expect(abuse).to.not.be.undefined
-
- expect(abuse.comment.text).to.be.empty
- expect(abuse.comment.video.name).to.equal('server 2')
- expect(abuse.comment.deleted).to.be.true
- })
-
- it('Should delete the comment abuse', async function () {
- await commands[1].delete({ abuseId: abuseServer2.id })
-
- await waitJobs(servers)
-
- {
- const body = await commands[1].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(0)
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await commands[0].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(2)
- }
- })
-
- it('Should list and filter video abuses', async function () {
- {
- const body = await commands[0].getAdminList({ filter: 'comment', searchReportee: 'foo' })
- expect(body.total).to.equal(0)
- }
-
- {
- const body = await commands[0].getAdminList({ filter: 'comment', searchReportee: 'ot' })
- expect(body.total).to.equal(2)
- }
-
- {
- const body = await commands[0].getAdminList({ filter: 'comment', start: 1, count: 1, sort: 'createdAt' })
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].comment.text).to.be.empty
- }
-
- {
- const body = await commands[0].getAdminList({ filter: 'comment', start: 1, count: 1, sort: '-createdAt' })
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].comment.text).to.equal('comment server 1')
- }
- })
- })
-
- describe('Account abuses', function () {
-
- function getAccountFromServer (server: PeerTubeServer, targetName: string, targetServer: PeerTubeServer) {
- return server.accounts.get({ accountName: targetName + '@' + targetServer.host })
- }
-
- before(async function () {
- this.timeout(50000)
-
- await servers[0].users.create({ username: 'user_1', password: 'donald' })
-
- const token = await servers[1].users.generateUserAndToken('user_2')
- await servers[1].videos.upload({ token, attributes: { name: 'super video' } })
-
- await waitJobs(servers)
- })
-
- it('Should report abuse on an account', async function () {
- this.timeout(15000)
-
- const account = await getAccountFromServer(servers[0], 'user_1', servers[0])
-
- const reason = 'it is a bad account'
- await commands[0].report({ accountId: account.id, reason })
-
- await waitJobs(servers)
- })
-
- it('Should have 1 account abuse on server 1 and 0 on server 2', async function () {
- {
- const body = await commands[0].getAdminList({ filter: 'account' })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const abuse = body.data[0]
- expect(abuse.reason).to.equal('it is a bad account')
-
- expect(abuse.reporterAccount.name).to.equal('root')
- expect(abuse.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse.video).to.be.null
- expect(abuse.comment).to.be.null
-
- expect(abuse.flaggedAccount.name).to.equal('user_1')
- expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
- }
-
- {
- const body = await commands[1].getAdminList({ filter: 'comment' })
- expect(body.total).to.equal(0)
- expect(body.data.length).to.equal(0)
- }
- })
-
- it('Should report abuse on a remote account', async function () {
- const account = await getAccountFromServer(servers[0], 'user_2', servers[1])
-
- const reason = 'it is a really bad account'
- await commands[0].report({ accountId: account.id, reason })
-
- await waitJobs(servers)
- })
-
- it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
- {
- const body = await commands[0].getAdminList({ filter: 'account' })
- expect(body.total).to.equal(2)
- expect(body.data.length).to.equal(2)
-
- const abuse: AdminAbuse = body.data[0]
- expect(abuse.reason).to.equal('it is a bad account')
-
- const abuse2: AdminAbuse = body.data[1]
- expect(abuse2.reason).to.equal('it is a really bad account')
-
- expect(abuse2.reporterAccount.name).to.equal('root')
- expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuse2.video).to.be.null
- expect(abuse2.comment).to.be.null
-
- expect(abuse2.state.id).to.equal(AbuseState.PENDING)
- expect(abuse2.state.label).to.equal('Pending')
-
- expect(abuse2.moderationComment).to.be.null
- }
-
- {
- const body = await commands[1].getAdminList({ filter: 'account' })
- expect(body.total).to.equal(1)
- expect(body.data.length).to.equal(1)
-
- abuseServer2 = body.data[0]
-
- expect(abuseServer2.reason).to.equal('it is a really bad account')
-
- expect(abuseServer2.reporterAccount.name).to.equal('root')
- expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
-
- expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
- expect(abuseServer2.state.label).to.equal('Pending')
-
- expect(abuseServer2.moderationComment).to.be.null
- }
- })
-
- it('Should keep the account abuse when deleting the account', async function () {
- const account = await getAccountFromServer(servers[1], 'user_2', servers[1])
- await servers[1].users.remove({ userId: account.userId })
-
- await waitJobs(servers)
-
- const body = await commands[0].getAdminList({ filter: 'account' })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- const abuse = body.data.find(a => a.reason === 'it is a really bad account')
- expect(abuse).to.not.be.undefined
- })
-
- it('Should delete the account abuse', async function () {
- await commands[1].delete({ abuseId: abuseServer2.id })
-
- await waitJobs(servers)
-
- {
- const body = await commands[1].getAdminList({ filter: 'account' })
- expect(body.total).to.equal(0)
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await commands[0].getAdminList({ filter: 'account' })
- expect(body.total).to.equal(2)
-
- abuseServer1 = body.data[0]
- }
- })
- })
-
- describe('Common actions on abuses', function () {
-
- it('Should update the state of an abuse', async function () {
- await commands[0].update({ abuseId: abuseServer1.id, body: { state: AbuseState.REJECTED } })
-
- const body = await commands[0].getAdminList({ id: abuseServer1.id })
- expect(body.data[0].state.id).to.equal(AbuseState.REJECTED)
- })
-
- it('Should add a moderation comment', async function () {
- await commands[0].update({ abuseId: abuseServer1.id, body: { state: AbuseState.ACCEPTED, moderationComment: 'Valid' } })
-
- const body = await commands[0].getAdminList({ id: abuseServer1.id })
- expect(body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
- expect(body.data[0].moderationComment).to.equal('Valid')
- })
- })
-
- describe('My abuses', async function () {
- let abuseId1: number
- let userAccessToken: string
-
- before(async function () {
- userAccessToken = await servers[0].users.generateUserAndToken('user_42')
-
- await commands[0].report({ token: userAccessToken, videoId: servers[0].store.videoCreated.id, reason: 'user reason 1' })
-
- const videoId = await servers[0].videos.getId({ uuid: servers[1].store.videoCreated.uuid })
- await commands[0].report({ token: userAccessToken, videoId, reason: 'user reason 2' })
- })
-
- it('Should correctly list my abuses', async function () {
- {
- const body = await commands[0].getUserList({ token: userAccessToken, start: 0, count: 5, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const abuses = body.data
- expect(abuses[0].reason).to.equal('user reason 1')
- expect(abuses[1].reason).to.equal('user reason 2')
-
- abuseId1 = abuses[0].id
- }
-
- {
- const body = await commands[0].getUserList({ token: userAccessToken, start: 1, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const abuses: UserAbuse[] = body.data
- expect(abuses[0].reason).to.equal('user reason 2')
- }
-
- {
- const body = await commands[0].getUserList({ token: userAccessToken, start: 1, count: 1, sort: '-createdAt' })
- expect(body.total).to.equal(2)
-
- const abuses: UserAbuse[] = body.data
- expect(abuses[0].reason).to.equal('user reason 1')
- }
- })
-
- it('Should correctly filter my abuses by id', async function () {
- const body = await commands[0].getUserList({ token: userAccessToken, id: abuseId1 })
- expect(body.total).to.equal(1)
-
- const abuses: UserAbuse[] = body.data
- expect(abuses[0].reason).to.equal('user reason 1')
- })
-
- it('Should correctly filter my abuses by search', async function () {
- const body = await commands[0].getUserList({ token: userAccessToken, search: 'server 2' })
- expect(body.total).to.equal(1)
-
- const abuses: UserAbuse[] = body.data
- expect(abuses[0].reason).to.equal('user reason 2')
- })
-
- it('Should correctly filter my abuses by state', async function () {
- await commands[0].update({ abuseId: abuseId1, body: { state: AbuseState.REJECTED } })
-
- const body = await commands[0].getUserList({ token: userAccessToken, state: AbuseState.REJECTED })
- expect(body.total).to.equal(1)
-
- const abuses: UserAbuse[] = body.data
- expect(abuses[0].reason).to.equal('user reason 1')
- })
- })
-
- describe('Abuse messages', async function () {
- let abuseId: number
- let userToken: string
- let abuseMessageUserId: number
- let abuseMessageModerationId: number
-
- before(async function () {
- userToken = await servers[0].users.generateUserAndToken('user_43')
-
- const body = await commands[0].report({ token: userToken, videoId: servers[0].store.videoCreated.id, reason: 'user 43 reason 1' })
- abuseId = body.abuse.id
- })
-
- it('Should create some messages on the abuse', async function () {
- await commands[0].addMessage({ token: userToken, abuseId, message: 'message 1' })
- await commands[0].addMessage({ abuseId, message: 'message 2' })
- await commands[0].addMessage({ abuseId, message: 'message 3' })
- await commands[0].addMessage({ token: userToken, abuseId, message: 'message 4' })
- })
-
- it('Should have the correct messages count when listing abuses', async function () {
- const results = await Promise.all([
- commands[0].getAdminList({ start: 0, count: 50 }),
- commands[0].getUserList({ token: userToken, start: 0, count: 50 })
- ])
-
- for (const body of results) {
- const abuses = body.data
- const abuse = abuses.find(a => a.id === abuseId)
- expect(abuse.countMessages).to.equal(4)
- }
- })
-
- it('Should correctly list messages of this abuse', async function () {
- const results = await Promise.all([
- commands[0].listMessages({ abuseId }),
- commands[0].listMessages({ token: userToken, abuseId })
- ])
-
- for (const body of results) {
- expect(body.total).to.equal(4)
-
- const abuseMessages: AbuseMessage[] = body.data
-
- expect(abuseMessages[0].message).to.equal('message 1')
- expect(abuseMessages[0].byModerator).to.be.false
- expect(abuseMessages[0].account.name).to.equal('user_43')
-
- abuseMessageUserId = abuseMessages[0].id
-
- expect(abuseMessages[1].message).to.equal('message 2')
- expect(abuseMessages[1].byModerator).to.be.true
- expect(abuseMessages[1].account.name).to.equal('root')
-
- expect(abuseMessages[2].message).to.equal('message 3')
- expect(abuseMessages[2].byModerator).to.be.true
- expect(abuseMessages[2].account.name).to.equal('root')
- abuseMessageModerationId = abuseMessages[2].id
-
- expect(abuseMessages[3].message).to.equal('message 4')
- expect(abuseMessages[3].byModerator).to.be.false
- expect(abuseMessages[3].account.name).to.equal('user_43')
- }
- })
-
- it('Should delete messages', async function () {
- await commands[0].deleteMessage({ abuseId, messageId: abuseMessageModerationId })
- await commands[0].deleteMessage({ token: userToken, abuseId, messageId: abuseMessageUserId })
-
- const results = await Promise.all([
- commands[0].listMessages({ abuseId }),
- commands[0].listMessages({ token: userToken, abuseId })
- ])
-
- for (const body of results) {
- expect(body.total).to.equal(2)
-
- const abuseMessages: AbuseMessage[] = body.data
- expect(abuseMessages[0].message).to.equal('message 2')
- expect(abuseMessages[1].message).to.equal('message 4')
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/moderation/blocklist-notification.ts b/server/tests/api/moderation/blocklist-notification.ts
deleted file mode 100644
index 9c2863a58..000000000
--- a/server/tests/api/moderation/blocklist-notification.ts
+++ /dev/null
@@ -1,231 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { UserNotificationType } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkNotifications (server: PeerTubeServer, token: string, expected: UserNotificationType[]) {
- const { data } = await server.notifications.list({ token, start: 0, count: 10, unread: true })
- expect(data).to.have.lengthOf(expected.length)
-
- for (const type of expected) {
- expect(data.find(n => n.type === type)).to.exist
- }
-}
-
-describe('Test blocklist notifications', function () {
- let servers: PeerTubeServer[]
- let videoUUID: string
-
- let userToken1: string
- let userToken2: string
- let remoteUserToken: string
-
- async function resetState () {
- try {
- await servers[1].subscriptions.remove({ token: remoteUserToken, uri: 'user1_channel@' + servers[0].host })
- await servers[1].subscriptions.remove({ token: remoteUserToken, uri: 'user2_channel@' + servers[0].host })
- } catch {}
-
- await waitJobs(servers)
-
- await servers[0].notifications.markAsReadAll({ token: userToken1 })
- await servers[0].notifications.markAsReadAll({ token: userToken2 })
-
- {
- const { uuid } = await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video' } })
- videoUUID = uuid
-
- await waitJobs(servers)
- }
-
- {
- await servers[1].comments.createThread({
- token: remoteUserToken,
- videoId: videoUUID,
- text: '@user2@' + servers[0].host + ' hello'
- })
- }
-
- {
-
- await servers[1].subscriptions.add({ token: remoteUserToken, targetUri: 'user1_channel@' + servers[0].host })
- await servers[1].subscriptions.add({ token: remoteUserToken, targetUri: 'user2_channel@' + servers[0].host })
- }
-
- await waitJobs(servers)
- }
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- {
- const user = { username: 'user1', password: 'password' }
- await servers[0].users.create({
- username: user.username,
- password: user.password,
- videoQuota: -1,
- videoQuotaDaily: -1
- })
-
- userToken1 = await servers[0].login.getAccessToken(user)
- await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video user 1' } })
- }
-
- {
- const user = { username: 'user2', password: 'password' }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- userToken2 = await servers[0].login.getAccessToken(user)
- }
-
- {
- const user = { username: 'user3', password: 'password' }
- await servers[1].users.create({ username: user.username, password: user.password })
-
- remoteUserToken = await servers[1].login.getAccessToken(user)
- }
-
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('User blocks another user', function () {
-
- before(async function () {
- this.timeout(30000)
-
- await resetState()
- })
-
- it('Should have appropriate notifications', async function () {
- const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken1, notifs)
- })
-
- it('Should block an account', async function () {
- await servers[0].blocklist.addToMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0], userToken1, [])
- })
-
- it('Should have notifications of this account on user 2', async function () {
- const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
-
- await checkNotifications(servers[0], userToken2, notifs)
-
- await servers[0].blocklist.removeFromMyBlocklist({ token: userToken1, account: 'user3@' + servers[1].host })
- })
- })
-
- describe('User blocks another server', function () {
-
- before(async function () {
- this.timeout(30000)
-
- await resetState()
- })
-
- it('Should have appropriate notifications', async function () {
- const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken1, notifs)
- })
-
- it('Should block an account', async function () {
- await servers[0].blocklist.addToMyBlocklist({ token: userToken1, server: servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0], userToken1, [])
- })
-
- it('Should have notifications of this account on user 2', async function () {
- const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
-
- await checkNotifications(servers[0], userToken2, notifs)
-
- await servers[0].blocklist.removeFromMyBlocklist({ token: userToken1, server: servers[1].host })
- })
- })
-
- describe('Server blocks a user', function () {
-
- before(async function () {
- this.timeout(30000)
-
- await resetState()
- })
-
- it('Should have appropriate notifications', async function () {
- {
- const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken1, notifs)
- }
-
- {
- const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken2, notifs)
- }
- })
-
- it('Should block an account', async function () {
- await servers[0].blocklist.addToServerBlocklist({ account: 'user3@' + servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0], userToken1, [])
- await checkNotifications(servers[0], userToken2, [])
-
- await servers[0].blocklist.removeFromServerBlocklist({ account: 'user3@' + servers[1].host })
- })
- })
-
- describe('Server blocks a server', function () {
-
- before(async function () {
- this.timeout(30000)
-
- await resetState()
- })
-
- it('Should have appropriate notifications', async function () {
- {
- const notifs = [ UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken1, notifs)
- }
-
- {
- const notifs = [ UserNotificationType.COMMENT_MENTION, UserNotificationType.NEW_FOLLOW ]
- await checkNotifications(servers[0], userToken2, notifs)
- }
- })
-
- it('Should block an account', async function () {
- await servers[0].blocklist.addToServerBlocklist({ server: servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not have notifications from this account', async function () {
- await checkNotifications(servers[0], userToken1, [])
- await checkNotifications(servers[0], userToken2, [])
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/moderation/blocklist.ts b/server/tests/api/moderation/blocklist.ts
deleted file mode 100644
index b90d8c16c..000000000
--- a/server/tests/api/moderation/blocklist.ts
+++ /dev/null
@@ -1,902 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { UserNotificationType } from '@shared/models'
-import {
- BlocklistCommand,
- cleanupTests,
- CommentsCommand,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkAllVideos (server: PeerTubeServer, token: string) {
- {
- const { data } = await server.videos.listWithToken({ token })
- expect(data).to.have.lengthOf(5)
- }
-
- {
- const { data } = await server.videos.list()
- expect(data).to.have.lengthOf(5)
- }
-}
-
-async function checkAllComments (server: PeerTubeServer, token: string, videoUUID: string) {
- const { data } = await server.comments.listThreads({ videoId: videoUUID, start: 0, count: 25, sort: '-createdAt', token })
-
- const threads = data.filter(t => t.isDeleted === false)
- expect(threads).to.have.lengthOf(2)
-
- for (const thread of threads) {
- const tree = await server.comments.getThread({ videoId: videoUUID, threadId: thread.id, token })
- expect(tree.children).to.have.lengthOf(1)
- }
-}
-
-async function checkCommentNotification (
- mainServer: PeerTubeServer,
- comment: { server: PeerTubeServer, token: string, videoUUID: string, text: string },
- check: 'presence' | 'absence'
-) {
- const command = comment.server.comments
-
- const { threadId, createdAt } = await command.createThread({ token: comment.token, videoId: comment.videoUUID, text: comment.text })
-
- await waitJobs([ mainServer, comment.server ])
-
- const { data } = await mainServer.notifications.list({ start: 0, count: 30 })
- const commentNotifications = data.filter(n => n.comment && n.comment.video.uuid === comment.videoUUID && n.createdAt >= createdAt)
-
- if (check === 'presence') expect(commentNotifications).to.have.lengthOf(1)
- else expect(commentNotifications).to.have.lengthOf(0)
-
- await command.delete({ token: comment.token, videoId: comment.videoUUID, commentId: threadId })
-
- await waitJobs([ mainServer, comment.server ])
-}
-
-describe('Test blocklist', function () {
- let servers: PeerTubeServer[]
- let videoUUID1: string
- let videoUUID2: string
- let videoUUID3: string
- let userToken1: string
- let userModeratorToken: string
- let userToken2: string
-
- let command: BlocklistCommand
- let commentsCommand: CommentsCommand[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
- await setAccessTokensToServers(servers)
- await setDefaultAccountAvatar(servers)
-
- command = servers[0].blocklist
- commentsCommand = servers.map(s => s.comments)
-
- {
- const user = { username: 'user1', password: 'password' }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- userToken1 = await servers[0].login.getAccessToken(user)
- await servers[0].videos.upload({ token: userToken1, attributes: { name: 'video user 1' } })
- }
-
- {
- const user = { username: 'moderator', password: 'password' }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- userModeratorToken = await servers[0].login.getAccessToken(user)
- }
-
- {
- const user = { username: 'user2', password: 'password' }
- await servers[1].users.create({ username: user.username, password: user.password })
-
- userToken2 = await servers[1].login.getAccessToken(user)
- await servers[1].videos.upload({ token: userToken2, attributes: { name: 'video user 2' } })
- }
-
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video server 1' } })
- videoUUID1 = uuid
- }
-
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video server 2' } })
- videoUUID2 = uuid
- }
-
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 2 server 1' } })
- videoUUID3 = uuid
- }
-
- await doubleFollow(servers[0], servers[1])
- await doubleFollow(servers[0], servers[2])
-
- {
- const created = await commentsCommand[0].createThread({ videoId: videoUUID1, text: 'comment root 1' })
- const reply = await commentsCommand[0].addReply({
- token: userToken1,
- videoId: videoUUID1,
- toCommentId: created.id,
- text: 'comment user 1'
- })
- await commentsCommand[0].addReply({ videoId: videoUUID1, toCommentId: reply.id, text: 'comment root 1' })
- }
-
- {
- const created = await commentsCommand[0].createThread({ token: userToken1, videoId: videoUUID1, text: 'comment user 1' })
- await commentsCommand[0].addReply({ videoId: videoUUID1, toCommentId: created.id, text: 'comment root 1' })
- }
-
- await waitJobs(servers)
- })
-
- describe('User blocklist', function () {
-
- describe('When managing account blocklist', function () {
- it('Should list all videos', function () {
- return checkAllVideos(servers[0], servers[0].accessToken)
- })
-
- it('Should list the comments', function () {
- return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- })
-
- it('Should block a remote account', async function () {
- await command.addToMyBlocklist({ account: 'user2@' + servers[1].host })
- })
-
- it('Should hide its videos', async function () {
- const { data } = await servers[0].videos.listWithToken()
-
- expect(data).to.have.lengthOf(4)
-
- const v = data.find(v => v.name === 'video user 2')
- expect(v).to.be.undefined
- })
-
- it('Should block a local account', async function () {
- await command.addToMyBlocklist({ account: 'user1' })
- })
-
- it('Should hide its videos', async function () {
- const { data } = await servers[0].videos.listWithToken()
-
- expect(data).to.have.lengthOf(3)
-
- const v = data.find(v => v.name === 'video user 1')
- expect(v).to.be.undefined
- })
-
- it('Should hide its comments', async function () {
- const { data } = await commentsCommand[0].listThreads({
- token: servers[0].accessToken,
- videoId: videoUUID1,
- start: 0,
- count: 25,
- sort: '-createdAt'
- })
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].totalReplies).to.equal(1)
-
- const t = data.find(t => t.text === 'comment user 1')
- expect(t).to.be.undefined
-
- for (const thread of data) {
- const tree = await commentsCommand[0].getThread({
- videoId: videoUUID1,
- threadId: thread.id,
- token: servers[0].accessToken
- })
- expect(tree.children).to.have.lengthOf(0)
- }
- })
-
- it('Should not have notifications from blocked accounts', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'hidden comment' }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
-
- {
- const comment = {
- server: servers[0],
- token: userToken1,
- videoUUID: videoUUID2,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
- })
-
- it('Should list all the videos with another user', async function () {
- return checkAllVideos(servers[0], userToken1)
- })
-
- it('Should list blocked accounts', async function () {
- {
- const body = await command.listMyAccountBlocklist({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('root')
- expect(block.byAccount.name).to.equal('root')
- expect(block.blockedAccount.displayName).to.equal('user2')
- expect(block.blockedAccount.name).to.equal('user2')
- expect(block.blockedAccount.host).to.equal('' + servers[1].host)
- }
-
- {
- const body = await command.listMyAccountBlocklist({ start: 1, count: 2, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('root')
- expect(block.byAccount.name).to.equal('root')
- expect(block.blockedAccount.displayName).to.equal('user1')
- expect(block.blockedAccount.name).to.equal('user1')
- expect(block.blockedAccount.host).to.equal('' + servers[0].host)
- }
- })
-
- it('Should search blocked accounts', async function () {
- const body = await command.listMyAccountBlocklist({ start: 0, count: 10, search: 'user2' })
- expect(body.total).to.equal(1)
-
- expect(body.data[0].blockedAccount.name).to.equal('user2')
- })
-
- it('Should get blocked status', async function () {
- const remoteHandle = 'user2@' + servers[1].host
- const localHandle = 'user1@' + servers[0].host
- const unknownHandle = 'user5@' + servers[0].host
-
- {
- const status = await command.getStatus({ accounts: [ remoteHandle ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(1)
- expect(status.accounts[remoteHandle].blockedByUser).to.be.false
- expect(status.accounts[remoteHandle].blockedByServer).to.be.false
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(0)
- }
-
- {
- const status = await command.getStatus({ token: servers[0].accessToken, accounts: [ remoteHandle ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(1)
- expect(status.accounts[remoteHandle].blockedByUser).to.be.true
- expect(status.accounts[remoteHandle].blockedByServer).to.be.false
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(0)
- }
-
- {
- const status = await command.getStatus({ token: servers[0].accessToken, accounts: [ localHandle, remoteHandle, unknownHandle ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(3)
-
- for (const handle of [ localHandle, remoteHandle ]) {
- expect(status.accounts[handle].blockedByUser).to.be.true
- expect(status.accounts[handle].blockedByServer).to.be.false
- }
-
- expect(status.accounts[unknownHandle].blockedByUser).to.be.false
- expect(status.accounts[unknownHandle].blockedByServer).to.be.false
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(0)
- }
- })
-
- it('Should not allow a remote blocked user to comment my videos', async function () {
- this.timeout(60000)
-
- {
- await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID3, text: 'comment user 2' })
- await waitJobs(servers)
-
- await commentsCommand[0].createThread({ token: servers[0].accessToken, videoId: videoUUID3, text: 'uploader' })
- await waitJobs(servers)
-
- const commentId = await commentsCommand[1].findCommentId({ videoId: videoUUID3, text: 'uploader' })
- const message = 'reply by user 2'
- const reply = await commentsCommand[1].addReply({ token: userToken2, videoId: videoUUID3, toCommentId: commentId, text: message })
- await commentsCommand[1].addReply({ videoId: videoUUID3, toCommentId: reply.id, text: 'another reply' })
-
- await waitJobs(servers)
- }
-
- // Server 2 has all the comments
- {
- const { data } = await commentsCommand[1].listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
-
- expect(data).to.have.lengthOf(2)
- expect(data[0].text).to.equal('uploader')
- expect(data[1].text).to.equal('comment user 2')
-
- const tree = await commentsCommand[1].getThread({ videoId: videoUUID3, threadId: data[0].id })
- expect(tree.children).to.have.lengthOf(1)
- expect(tree.children[0].comment.text).to.equal('reply by user 2')
- expect(tree.children[0].children).to.have.lengthOf(1)
- expect(tree.children[0].children[0].comment.text).to.equal('another reply')
- }
-
- // Server 1 and 3 should only have uploader comments
- for (const server of [ servers[0], servers[2] ]) {
- const { data } = await server.comments.listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].text).to.equal('uploader')
-
- const tree = await server.comments.getThread({ videoId: videoUUID3, threadId: data[0].id })
-
- if (server.serverNumber === 1) expect(tree.children).to.have.lengthOf(0)
- else expect(tree.children).to.have.lengthOf(1)
- }
- })
-
- it('Should unblock the remote account', async function () {
- await command.removeFromMyBlocklist({ account: 'user2@' + servers[1].host })
- })
-
- it('Should display its videos', async function () {
- const { data } = await servers[0].videos.listWithToken()
- expect(data).to.have.lengthOf(4)
-
- const v = data.find(v => v.name === 'video user 2')
- expect(v).not.to.be.undefined
- })
-
- it('Should display its comments on my video', async function () {
- for (const server of servers) {
- const { data } = await server.comments.listThreads({ videoId: videoUUID3, count: 25, sort: '-createdAt' })
-
- // Server 3 should not have 2 comment threads, because server 1 did not forward the server 2 comment
- if (server.serverNumber === 3) {
- expect(data).to.have.lengthOf(1)
- continue
- }
-
- expect(data).to.have.lengthOf(2)
- expect(data[0].text).to.equal('uploader')
- expect(data[1].text).to.equal('comment user 2')
-
- const tree = await server.comments.getThread({ videoId: videoUUID3, threadId: data[0].id })
- expect(tree.children).to.have.lengthOf(1)
- expect(tree.children[0].comment.text).to.equal('reply by user 2')
- expect(tree.children[0].children).to.have.lengthOf(1)
- expect(tree.children[0].children[0].comment.text).to.equal('another reply')
- }
- })
-
- it('Should unblock the local account', async function () {
- await command.removeFromMyBlocklist({ account: 'user1' })
- })
-
- it('Should display its comments', function () {
- return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- })
-
- it('Should have a notification from a non blocked account', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
-
- {
- const comment = {
- server: servers[0],
- token: userToken1,
- videoUUID: videoUUID2,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
- })
- })
-
- describe('When managing server blocklist', function () {
-
- it('Should list all videos', function () {
- return checkAllVideos(servers[0], servers[0].accessToken)
- })
-
- it('Should list the comments', function () {
- return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- })
-
- it('Should block a remote server', async function () {
- await command.addToMyBlocklist({ server: '' + servers[1].host })
- })
-
- it('Should hide its videos', async function () {
- const { data } = await servers[0].videos.listWithToken()
-
- expect(data).to.have.lengthOf(3)
-
- const v1 = data.find(v => v.name === 'video user 2')
- const v2 = data.find(v => v.name === 'video server 2')
-
- expect(v1).to.be.undefined
- expect(v2).to.be.undefined
- })
-
- it('Should list all the videos with another user', async function () {
- return checkAllVideos(servers[0], userToken1)
- })
-
- it('Should hide its comments', async function () {
- const { id } = await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID1, text: 'hidden comment 2' })
-
- await waitJobs(servers)
-
- await checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
-
- await commentsCommand[1].delete({ token: userToken2, videoId: videoUUID1, commentId: id })
- })
-
- it('Should not have notifications from blocked server', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'hidden comment' }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
- })
-
- it('Should list blocked servers', async function () {
- const body = await command.listMyServerBlocklist({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('root')
- expect(block.byAccount.name).to.equal('root')
- expect(block.blockedServer.host).to.equal('' + servers[1].host)
- })
-
- it('Should search blocked servers', async function () {
- const body = await command.listMyServerBlocklist({ start: 0, count: 10, search: servers[1].host })
- expect(body.total).to.equal(1)
-
- expect(body.data[0].blockedServer.host).to.equal(servers[1].host)
- })
-
- it('Should get blocklist status', async function () {
- const blockedServer = servers[1].host
- const notBlockedServer = 'example.com'
-
- {
- const status = await command.getStatus({ hosts: [ blockedServer, notBlockedServer ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(0)
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(2)
- expect(status.hosts[blockedServer].blockedByUser).to.be.false
- expect(status.hosts[blockedServer].blockedByServer).to.be.false
-
- expect(status.hosts[notBlockedServer].blockedByUser).to.be.false
- expect(status.hosts[notBlockedServer].blockedByServer).to.be.false
- }
-
- {
- const status = await command.getStatus({ token: servers[0].accessToken, hosts: [ blockedServer, notBlockedServer ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(0)
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(2)
- expect(status.hosts[blockedServer].blockedByUser).to.be.true
- expect(status.hosts[blockedServer].blockedByServer).to.be.false
-
- expect(status.hosts[notBlockedServer].blockedByUser).to.be.false
- expect(status.hosts[notBlockedServer].blockedByServer).to.be.false
- }
- })
-
- it('Should unblock the remote server', async function () {
- await command.removeFromMyBlocklist({ server: '' + servers[1].host })
- })
-
- it('Should display its videos', function () {
- return checkAllVideos(servers[0], servers[0].accessToken)
- })
-
- it('Should display its comments', function () {
- return checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
- })
-
- it('Should have notification from unblocked server', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
- })
- })
- })
-
- describe('Server blocklist', function () {
-
- describe('When managing account blocklist', function () {
- it('Should list all videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0], token)
- }
- })
-
- it('Should list the comments', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0], token, videoUUID1)
- }
- })
-
- it('Should block a remote account', async function () {
- await command.addToServerBlocklist({ account: 'user2@' + servers[1].host })
- })
-
- it('Should hide its videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const { data } = await servers[0].videos.listWithToken({ token })
-
- expect(data).to.have.lengthOf(4)
-
- const v = data.find(v => v.name === 'video user 2')
- expect(v).to.be.undefined
- }
- })
-
- it('Should block a local account', async function () {
- await command.addToServerBlocklist({ account: 'user1' })
- })
-
- it('Should hide its videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const { data } = await servers[0].videos.listWithToken({ token })
-
- expect(data).to.have.lengthOf(3)
-
- const v = data.find(v => v.name === 'video user 1')
- expect(v).to.be.undefined
- }
- })
-
- it('Should hide its comments', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const { data } = await commentsCommand[0].listThreads({ videoId: videoUUID1, count: 20, sort: '-createdAt', token })
- const threads = data.filter(t => t.isDeleted === false)
-
- expect(threads).to.have.lengthOf(1)
- expect(threads[0].totalReplies).to.equal(1)
-
- const t = threads.find(t => t.text === 'comment user 1')
- expect(t).to.be.undefined
-
- for (const thread of threads) {
- const tree = await commentsCommand[0].getThread({ videoId: videoUUID1, threadId: thread.id, token })
- expect(tree.children).to.have.lengthOf(0)
- }
- }
- })
-
- it('Should not have notification from blocked accounts by instance', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'hidden comment' }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
- })
-
- it('Should list blocked accounts', async function () {
- {
- const body = await command.listServerAccountBlocklist({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('peertube')
- expect(block.byAccount.name).to.equal('peertube')
- expect(block.blockedAccount.displayName).to.equal('user2')
- expect(block.blockedAccount.name).to.equal('user2')
- expect(block.blockedAccount.host).to.equal('' + servers[1].host)
- }
-
- {
- const body = await command.listServerAccountBlocklist({ start: 1, count: 2, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('peertube')
- expect(block.byAccount.name).to.equal('peertube')
- expect(block.blockedAccount.displayName).to.equal('user1')
- expect(block.blockedAccount.name).to.equal('user1')
- expect(block.blockedAccount.host).to.equal('' + servers[0].host)
- }
- })
-
- it('Should search blocked accounts', async function () {
- const body = await command.listServerAccountBlocklist({ start: 0, count: 10, search: 'user2' })
- expect(body.total).to.equal(1)
-
- expect(body.data[0].blockedAccount.name).to.equal('user2')
- })
-
- it('Should get blocked status', async function () {
- const remoteHandle = 'user2@' + servers[1].host
- const localHandle = 'user1@' + servers[0].host
- const unknownHandle = 'user5@' + servers[0].host
-
- for (const token of [ undefined, servers[0].accessToken ]) {
- const status = await command.getStatus({ token, accounts: [ localHandle, remoteHandle, unknownHandle ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(3)
-
- for (const handle of [ localHandle, remoteHandle ]) {
- expect(status.accounts[handle].blockedByUser).to.be.false
- expect(status.accounts[handle].blockedByServer).to.be.true
- }
-
- expect(status.accounts[unknownHandle].blockedByUser).to.be.false
- expect(status.accounts[unknownHandle].blockedByServer).to.be.false
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(0)
- }
- })
-
- it('Should unblock the remote account', async function () {
- await command.removeFromServerBlocklist({ account: 'user2@' + servers[1].host })
- })
-
- it('Should display its videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const { data } = await servers[0].videos.listWithToken({ token })
- expect(data).to.have.lengthOf(4)
-
- const v = data.find(v => v.name === 'video user 2')
- expect(v).not.to.be.undefined
- }
- })
-
- it('Should unblock the local account', async function () {
- await command.removeFromServerBlocklist({ account: 'user1' })
- })
-
- it('Should display its comments', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0], token, videoUUID1)
- }
- })
-
- it('Should have notifications from unblocked accounts', async function () {
- this.timeout(20000)
-
- {
- const comment = { server: servers[0], token: userToken1, videoUUID: videoUUID1, text: 'displayed comment' }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
- })
- })
-
- describe('When managing server blocklist', function () {
-
- it('Should list all videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0], token)
- }
- })
-
- it('Should list the comments', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0], token, videoUUID1)
- }
- })
-
- it('Should block a remote server', async function () {
- await command.addToServerBlocklist({ server: '' + servers[1].host })
- })
-
- it('Should hide its videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- const requests = [
- servers[0].videos.list(),
- servers[0].videos.listWithToken({ token })
- ]
-
- for (const req of requests) {
- const { data } = await req
- expect(data).to.have.lengthOf(3)
-
- const v1 = data.find(v => v.name === 'video user 2')
- const v2 = data.find(v => v.name === 'video server 2')
-
- expect(v1).to.be.undefined
- expect(v2).to.be.undefined
- }
- }
- })
-
- it('Should hide its comments', async function () {
- const { id } = await commentsCommand[1].createThread({ token: userToken2, videoId: videoUUID1, text: 'hidden comment 2' })
-
- await waitJobs(servers)
-
- await checkAllComments(servers[0], servers[0].accessToken, videoUUID1)
-
- await commentsCommand[1].delete({ token: userToken2, videoId: videoUUID1, commentId: id })
- })
-
- it('Should not have notification from blocked instances by instance', async function () {
- this.timeout(50000)
-
- {
- const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'hidden comment' }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'absence')
- }
-
- {
- const now = new Date()
- await servers[1].follows.unfollow({ target: servers[0] })
- await waitJobs(servers)
- await servers[1].follows.follow({ hosts: [ servers[0].host ] })
-
- await waitJobs(servers)
-
- const { data } = await servers[0].notifications.list({ start: 0, count: 30 })
- const commentNotifications = data.filter(n => {
- return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
- })
-
- expect(commentNotifications).to.have.lengthOf(0)
- }
- })
-
- it('Should list blocked servers', async function () {
- const body = await command.listServerServerBlocklist({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const block = body.data[0]
- expect(block.byAccount.displayName).to.equal('peertube')
- expect(block.byAccount.name).to.equal('peertube')
- expect(block.blockedServer.host).to.equal('' + servers[1].host)
- })
-
- it('Should search blocked servers', async function () {
- const body = await command.listServerServerBlocklist({ start: 0, count: 10, search: servers[1].host })
- expect(body.total).to.equal(1)
-
- expect(body.data[0].blockedServer.host).to.equal(servers[1].host)
- })
-
- it('Should get blocklist status', async function () {
- const blockedServer = servers[1].host
- const notBlockedServer = 'example.com'
-
- for (const token of [ undefined, servers[0].accessToken ]) {
- const status = await command.getStatus({ token, hosts: [ blockedServer, notBlockedServer ] })
- expect(Object.keys(status.accounts)).to.have.lengthOf(0)
-
- expect(Object.keys(status.hosts)).to.have.lengthOf(2)
- expect(status.hosts[blockedServer].blockedByUser).to.be.false
- expect(status.hosts[blockedServer].blockedByServer).to.be.true
-
- expect(status.hosts[notBlockedServer].blockedByUser).to.be.false
- expect(status.hosts[notBlockedServer].blockedByServer).to.be.false
- }
- })
-
- it('Should unblock the remote server', async function () {
- await command.removeFromServerBlocklist({ server: '' + servers[1].host })
- })
-
- it('Should list all videos', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllVideos(servers[0], token)
- }
- })
-
- it('Should list the comments', async function () {
- for (const token of [ userModeratorToken, servers[0].accessToken ]) {
- await checkAllComments(servers[0], token, videoUUID1)
- }
- })
-
- it('Should have notification from unblocked instances', async function () {
- this.timeout(50000)
-
- {
- const comment = { server: servers[1], token: userToken2, videoUUID: videoUUID1, text: 'displayed comment' }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
-
- {
- const comment = {
- server: servers[1],
- token: userToken2,
- videoUUID: videoUUID1,
- text: 'hello @root@' + servers[0].host
- }
- await checkCommentNotification(servers[0], comment, 'presence')
- }
-
- {
- const now = new Date()
- await servers[1].follows.unfollow({ target: servers[0] })
- await waitJobs(servers)
- await servers[1].follows.follow({ hosts: [ servers[0].host ] })
-
- await waitJobs(servers)
-
- const { data } = await servers[0].notifications.list({ start: 0, count: 30 })
- const commentNotifications = data.filter(n => {
- return n.type === UserNotificationType.NEW_INSTANCE_FOLLOWER && n.createdAt >= now.toISOString()
- })
-
- expect(commentNotifications).to.have.lengthOf(1)
- }
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/moderation/index.ts b/server/tests/api/moderation/index.ts
deleted file mode 100644
index 874be03d5..000000000
--- a/server/tests/api/moderation/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './abuses'
-export * from './blocklist-notification'
-export * from './blocklist'
-export * from './video-blacklist'
diff --git a/server/tests/api/moderation/video-blacklist.ts b/server/tests/api/moderation/video-blacklist.ts
deleted file mode 100644
index ef087a93b..000000000
--- a/server/tests/api/moderation/video-blacklist.ts
+++ /dev/null
@@ -1,414 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { sortObjectComparator } from '@shared/core-utils'
-import { UserAdminFlag, UserRole, VideoBlacklist, VideoBlacklistType } from '@shared/models'
-import {
- BlacklistCommand,
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video blacklist', function () {
- let servers: PeerTubeServer[] = []
- let videoId: number
- let command: BlacklistCommand
-
- async function blacklistVideosOnServer (server: PeerTubeServer) {
- const { data } = await server.videos.list()
-
- for (const video of data) {
- await server.blacklist.add({ videoId: video.id, reason: 'super reason' })
- }
- }
-
- before(async function () {
- this.timeout(120000)
-
- // Run servers
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- await setDefaultChannelAvatar(servers[0])
-
- // Upload 2 videos on server 2
- await servers[1].videos.upload({ attributes: { name: 'My 1st video', description: 'A video on server 2' } })
- await servers[1].videos.upload({ attributes: { name: 'My 2nd video', description: 'A video on server 2' } })
-
- // Wait videos propagation, server 2 has transcoding enabled
- await waitJobs(servers)
-
- command = servers[0].blacklist
-
- // Blacklist the two videos on server 1
- await blacklistVideosOnServer(servers[0])
- })
-
- describe('When listing/searching videos', function () {
-
- it('Should not have the video blacklisted in videos list/search on server 1', async function () {
- {
- const { total, data } = await servers[0].videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(0)
- }
-
- {
- const body = await servers[0].search.searchVideos({ search: 'video' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
- })
-
- it('Should have the blacklisted video in videos list/search on server 2', async function () {
- {
- const { total, data } = await servers[1].videos.list()
-
- expect(total).to.equal(2)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(2)
- }
-
- {
- const body = await servers[1].search.searchVideos({ search: 'video' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(2)
- }
- })
- })
-
- describe('When listing manually blacklisted videos', function () {
- it('Should display all the blacklisted videos', async function () {
- const body = await command.list()
- expect(body.total).to.equal(2)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- for (const blacklistedVideo of blacklistedVideos) {
- expect(blacklistedVideo.reason).to.equal('super reason')
- videoId = blacklistedVideo.video.id
- }
- })
-
- it('Should display all the blacklisted videos when applying manual type filter', async function () {
- const body = await command.list({ type: VideoBlacklistType.MANUAL })
- expect(body.total).to.equal(2)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
- })
-
- it('Should display nothing when applying automatic type filter', async function () {
- const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
- expect(body.total).to.equal(0)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(0)
- })
-
- it('Should get the correct sort when sorting by descending id', async function () {
- const body = await command.list({ sort: '-id' })
- expect(body.total).to.equal(2)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = [ ...body.data ].sort(sortObjectComparator('id', 'desc'))
- expect(blacklistedVideos).to.deep.equal(result)
- })
-
- it('Should get the correct sort when sorting by descending video name', async function () {
- const body = await command.list({ sort: '-name' })
- expect(body.total).to.equal(2)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = [ ...body.data ].sort(sortObjectComparator('name', 'desc'))
- expect(blacklistedVideos).to.deep.equal(result)
- })
-
- it('Should get the correct sort when sorting by ascending creation date', async function () {
- const body = await command.list({ sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const blacklistedVideos = body.data
- expect(blacklistedVideos).to.be.an('array')
- expect(blacklistedVideos.length).to.equal(2)
-
- const result = [ ...body.data ].sort(sortObjectComparator('createdAt', 'asc'))
- expect(blacklistedVideos).to.deep.equal(result)
- })
- })
-
- describe('When updating blacklisted videos', function () {
- it('Should change the reason', async function () {
- await command.update({ videoId, reason: 'my super reason updated' })
-
- const body = await command.list({ sort: '-name' })
- const video = body.data.find(b => b.video.id === videoId)
-
- expect(video.reason).to.equal('my super reason updated')
- })
- })
-
- describe('When listing my videos', function () {
- it('Should display blacklisted videos', async function () {
- await blacklistVideosOnServer(servers[1])
-
- const { total, data } = await servers[1].videos.listMyVideos()
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const video of data) {
- expect(video.blacklisted).to.be.true
- expect(video.blacklistedReason).to.equal('super reason')
- }
- })
- })
-
- describe('When removing a blacklisted video', function () {
- let videoToRemove: VideoBlacklist
- let blacklist = []
-
- it('Should not have any video in videos list on server 1', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(0)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(0)
- })
-
- it('Should remove a video from the blacklist on server 1', async function () {
- // Get one video in the blacklist
- const body = await command.list({ sort: '-name' })
- videoToRemove = body.data[0]
- blacklist = body.data.slice(1)
-
- // Remove it
- await command.remove({ videoId: videoToRemove.video.id })
- })
-
- it('Should have the ex-blacklisted video in videos list on server 1', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(1)
-
- expect(data).to.be.an('array')
- expect(data.length).to.equal(1)
-
- expect(data[0].name).to.equal(videoToRemove.video.name)
- expect(data[0].id).to.equal(videoToRemove.video.id)
- })
-
- it('Should not have the ex-blacklisted video in videos blacklist list on server 1', async function () {
- const body = await command.list({ sort: '-name' })
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos.length).to.equal(1)
- expect(videos).to.deep.equal(blacklist)
- })
- })
-
- describe('When blacklisting local videos', function () {
- let video3UUID: string
- let video4UUID: string
-
- before(async function () {
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'Video 3' } })
- video3UUID = uuid
- }
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'Video 4' } })
- video4UUID = uuid
- }
-
- await waitJobs(servers)
- })
-
- it('Should blacklist video 3 and keep it federated', async function () {
- await command.add({ videoId: video3UUID, reason: 'super reason', unfederate: false })
-
- await waitJobs(servers)
-
- {
- const { data } = await servers[0].videos.list()
- expect(data.find(v => v.uuid === video3UUID)).to.be.undefined
- }
-
- {
- const { data } = await servers[1].videos.list()
- expect(data.find(v => v.uuid === video3UUID)).to.not.be.undefined
- }
- })
-
- it('Should unfederate the video', async function () {
- await command.add({ videoId: video4UUID, reason: 'super reason', unfederate: true })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data.find(v => v.uuid === video4UUID)).to.be.undefined
- }
- })
-
- it('Should have the video unfederated even after an Update AP message', async function () {
- await servers[0].videos.update({ id: video4UUID, attributes: { description: 'super description' } })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data.find(v => v.uuid === video4UUID)).to.be.undefined
- }
- })
-
- it('Should have the correct video blacklist unfederate attribute', async function () {
- const body = await command.list({ sort: 'createdAt' })
-
- const blacklistedVideos = body.data
- const video3Blacklisted = blacklistedVideos.find(b => b.video.uuid === video3UUID)
- const video4Blacklisted = blacklistedVideos.find(b => b.video.uuid === video4UUID)
-
- expect(video3Blacklisted.unfederated).to.be.false
- expect(video4Blacklisted.unfederated).to.be.true
- })
-
- it('Should remove the video from blacklist and refederate the video', async function () {
- await command.remove({ videoId: video4UUID })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data.find(v => v.uuid === video4UUID)).to.not.be.undefined
- }
- })
-
- })
-
- describe('When auto blacklist videos', function () {
- let userWithoutFlag: string
- let userWithFlag: string
- let channelOfUserWithoutFlag: number
-
- before(async function () {
- this.timeout(20000)
-
- await killallServers([ servers[0] ])
-
- const config = {
- auto_blacklist: {
- videos: {
- of_users: {
- enabled: true
- }
- }
- }
- }
- await servers[0].run(config)
-
- {
- const user = { username: 'user_without_flag', password: 'password' }
- await servers[0].users.create({
- username: user.username,
- adminFlags: UserAdminFlag.NONE,
- password: user.password,
- role: UserRole.USER
- })
-
- userWithoutFlag = await servers[0].login.getAccessToken(user)
-
- const { videoChannels } = await servers[0].users.getMyInfo({ token: userWithoutFlag })
- channelOfUserWithoutFlag = videoChannels[0].id
- }
-
- {
- const user = { username: 'user_with_flag', password: 'password' }
- await servers[0].users.create({
- username: user.username,
- adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST,
- password: user.password,
- role: UserRole.USER
- })
-
- userWithFlag = await servers[0].login.getAccessToken(user)
- }
-
- await waitJobs(servers)
- })
-
- it('Should auto blacklist a video on upload', async function () {
- await servers[0].videos.upload({ token: userWithoutFlag, attributes: { name: 'blacklisted' } })
-
- const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
- expect(body.total).to.equal(1)
- expect(body.data[0].video.name).to.equal('blacklisted')
- })
-
- it('Should auto blacklist a video on URL import', async function () {
- this.timeout(15000)
-
- const attributes = {
- targetUrl: FIXTURE_URLS.goodVideo,
- name: 'URL import',
- channelId: channelOfUserWithoutFlag
- }
- await servers[0].imports.importVideo({ token: userWithoutFlag, attributes })
-
- const body = await command.list({ sort: 'createdAt', type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
- expect(body.total).to.equal(2)
- expect(body.data[1].video.name).to.equal('URL import')
- })
-
- it('Should auto blacklist a video on torrent import', async function () {
- const attributes = {
- magnetUri: FIXTURE_URLS.magnet,
- name: 'Torrent import',
- channelId: channelOfUserWithoutFlag
- }
- await servers[0].imports.importVideo({ token: userWithoutFlag, attributes })
-
- const body = await command.list({ sort: 'createdAt', type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
- expect(body.total).to.equal(3)
- expect(body.data[2].video.name).to.equal('Torrent import')
- })
-
- it('Should not auto blacklist a video on upload if the user has the bypass blacklist flag', async function () {
- await servers[0].videos.upload({ token: userWithFlag, attributes: { name: 'not blacklisted' } })
-
- const body = await command.list({ type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED })
- expect(body.total).to.equal(3)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/notifications/admin-notifications.ts b/server/tests/api/notifications/admin-notifications.ts
deleted file mode 100644
index 4824542c9..000000000
--- a/server/tests/api/notifications/admin-notifications.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- CheckerBaseParams,
- checkNewPeerTubeVersion,
- checkNewPluginVersion,
- MockJoinPeerTubeVersions,
- MockSmtpServer,
- prepareNotificationsTest,
- SQLCommand
-} from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { PluginType, UserNotification, UserNotificationType } from '@shared/models'
-import { cleanupTests, PeerTubeServer } from '@shared/server-commands'
-
-describe('Test admin notifications', function () {
- let server: PeerTubeServer
- let sqlCommand: SQLCommand
- let userNotifications: UserNotification[] = []
- let adminNotifications: UserNotification[] = []
- let emails: object[] = []
- let baseParams: CheckerBaseParams
- let joinPeerTubeServer: MockJoinPeerTubeVersions
-
- before(async function () {
- this.timeout(120000)
-
- joinPeerTubeServer = new MockJoinPeerTubeVersions()
- const port = await joinPeerTubeServer.initialize()
-
- const config = {
- peertube: {
- check_latest_version: {
- enabled: true,
- url: `http://127.0.0.1:${port}/versions.json`
- }
- },
- plugins: {
- index: {
- enabled: true,
- check_latest_versions_interval: '3 seconds'
- }
- }
- }
-
- const res = await prepareNotificationsTest(1, config)
- emails = res.emails
- server = res.servers[0]
-
- userNotifications = res.userNotifications
- adminNotifications = res.adminNotifications
-
- baseParams = {
- server,
- emails,
- socketNotifications: adminNotifications,
- token: server.accessToken
- }
-
- await server.plugins.install({ npmName: 'peertube-plugin-hello-world' })
- await server.plugins.install({ npmName: 'peertube-theme-background-red' })
-
- sqlCommand = new SQLCommand(server)
- })
-
- describe('Latest PeerTube version notification', function () {
-
- it('Should not send a notification to admins if there is no new version', async function () {
- this.timeout(30000)
-
- joinPeerTubeServer.setLatestVersion('1.4.2')
-
- await wait(3000)
- await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '1.4.2', checkType: 'absence' })
- })
-
- it('Should send a notification to admins on new version', async function () {
- this.timeout(30000)
-
- joinPeerTubeServer.setLatestVersion('15.4.2')
-
- await wait(3000)
- await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '15.4.2', checkType: 'presence' })
- })
-
- it('Should not send the same notification to admins', async function () {
- this.timeout(30000)
-
- await wait(3000)
- expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(1)
- })
-
- it('Should not have sent a notification to users', async function () {
- this.timeout(30000)
-
- expect(userNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(0)
- })
-
- it('Should send a new notification after a new release', async function () {
- this.timeout(30000)
-
- joinPeerTubeServer.setLatestVersion('15.4.3')
-
- await wait(3000)
- await checkNewPeerTubeVersion({ ...baseParams, latestVersion: '15.4.3', checkType: 'presence' })
- expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
- })
- })
-
- describe('Latest plugin version notification', function () {
-
- it('Should not send a notification to admins if there is no new plugin version', async function () {
- this.timeout(30000)
-
- await wait(6000)
- await checkNewPluginVersion({ ...baseParams, pluginType: PluginType.PLUGIN, pluginName: 'hello-world', checkType: 'absence' })
- })
-
- it('Should send a notification to admins on new plugin version', async function () {
- this.timeout(30000)
-
- await sqlCommand.setPluginVersion('hello-world', '0.0.1')
- await sqlCommand.setPluginLatestVersion('hello-world', '0.0.1')
- await wait(6000)
-
- await checkNewPluginVersion({ ...baseParams, pluginType: PluginType.PLUGIN, pluginName: 'hello-world', checkType: 'presence' })
- })
-
- it('Should not send the same notification to admins', async function () {
- this.timeout(30000)
-
- await wait(6000)
-
- expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PLUGIN_VERSION)).to.have.lengthOf(1)
- })
-
- it('Should not have sent a notification to users', async function () {
- expect(userNotifications.filter(n => n.type === UserNotificationType.NEW_PLUGIN_VERSION)).to.have.lengthOf(0)
- })
-
- it('Should send a new notification after a new plugin release', async function () {
- this.timeout(30000)
-
- await sqlCommand.setPluginVersion('hello-world', '0.0.1')
- await sqlCommand.setPluginLatestVersion('hello-world', '0.0.1')
- await wait(6000)
-
- expect(adminNotifications.filter(n => n.type === UserNotificationType.NEW_PEERTUBE_VERSION)).to.have.lengthOf(2)
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await sqlCommand.cleanup()
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/notifications/comments-notifications.ts b/server/tests/api/notifications/comments-notifications.ts
deleted file mode 100644
index 0a4bfc5e4..000000000
--- a/server/tests/api/notifications/comments-notifications.ts
+++ /dev/null
@@ -1,305 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- checkCommentMention,
- CheckerBaseParams,
- checkNewCommentOnMyVideo,
- MockSmtpServer,
- prepareNotificationsTest
-} from '@server/tests/shared'
-import { UserNotification } from '@shared/models'
-import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
-
-describe('Test comments notifications', function () {
- let servers: PeerTubeServer[] = []
- let userToken: string
- let userNotifications: UserNotification[] = []
- let emails: object[] = []
-
- const commentText = '**hello** world, what do you think about peertube?
'
- const expectedHtml = 'hello world' +
- ',
what do you think about peertube?'
-
- before(async function () {
- this.timeout(120000)
-
- const res = await prepareNotificationsTest(2)
- emails = res.emails
- userToken = res.userAccessToken
- servers = res.servers
- userNotifications = res.userNotifications
- })
-
- describe('Comment on my video notifications', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken
- }
- })
-
- it('Should not send a new comment notification after a comment on another video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
- const commentId = created.id
-
- await waitJobs(servers)
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
- })
-
- it('Should not send a new comment notification if I comment my own video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- const created = await servers[0].comments.createThread({ token: userToken, videoId: uuid, text: 'comment' })
- const commentId = created.id
-
- await waitJobs(servers)
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
- })
-
- it('Should not send a new comment notification if the account is muted', async function () {
- this.timeout(30000)
-
- await servers[0].blocklist.addToMyBlocklist({ token: userToken, account: 'root' })
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
- const commentId = created.id
-
- await waitJobs(servers)
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'absence' })
-
- await servers[0].blocklist.removeFromMyBlocklist({ token: userToken, account: 'root' })
- })
-
- it('Should send a new comment notification after a local comment on my video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- const created = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
- const commentId = created.id
-
- await waitJobs(servers)
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'presence' })
- })
-
- it('Should send a new comment notification after a remote comment on my video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- await waitJobs(servers)
-
- await servers[1].comments.createThread({ videoId: uuid, text: 'comment' })
-
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: uuid })
- expect(data).to.have.lengthOf(1)
-
- const commentId = data[0].id
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId: commentId, commentId, checkType: 'presence' })
- })
-
- it('Should send a new comment notification after a local reply on my video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
-
- const { id: commentId } = await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'reply' })
-
- await waitJobs(servers)
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId, commentId, checkType: 'presence' })
- })
-
- it('Should send a new comment notification after a remote reply on my video', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
- await waitJobs(servers)
-
- {
- const created = await servers[1].comments.createThread({ videoId: uuid, text: 'comment' })
- const threadId = created.id
- await servers[1].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'reply' })
- }
-
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: uuid })
- expect(data).to.have.lengthOf(1)
-
- const threadId = data[0].id
- const tree = await servers[0].comments.getThread({ videoId: uuid, threadId })
-
- expect(tree.children).to.have.lengthOf(1)
- const commentId = tree.children[0].comment.id
-
- await checkNewCommentOnMyVideo({ ...baseParams, shortUUID, threadId, commentId, checkType: 'presence' })
- })
-
- it('Should convert markdown in comment to html', async function () {
- this.timeout(30000)
-
- const { uuid } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'cool video' } })
-
- await servers[0].comments.createThread({ videoId: uuid, text: commentText })
-
- await waitJobs(servers)
-
- const latestEmail = emails[emails.length - 1]
- expect(latestEmail['html']).to.contain(expectedHtml)
- })
- })
-
- describe('Mention notifications', function () {
- let baseParams: CheckerBaseParams
- const byAccountDisplayName = 'super root name'
-
- before(async function () {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken
- }
-
- await servers[0].users.updateMe({ displayName: 'super root name' })
- await servers[1].users.updateMe({ displayName: 'super root 2 name' })
- })
-
- it('Should not send a new mention comment notification if I mention the video owner', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken, attributes: { name: 'super video' } })
-
- const { id: commentId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
-
- await waitJobs(servers)
- await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
- })
-
- it('Should not send a new mention comment notification if I mention myself', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- const { id: commentId } = await servers[0].comments.createThread({ token: userToken, videoId: uuid, text: '@user_1 hello' })
-
- await waitJobs(servers)
- await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
- })
-
- it('Should not send a new mention notification if the account is muted', async function () {
- this.timeout(30000)
-
- await servers[0].blocklist.addToMyBlocklist({ token: userToken, account: 'root' })
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- const { id: commentId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
-
- await waitJobs(servers)
- await checkCommentMention({ ...baseParams, shortUUID, threadId: commentId, commentId, byAccountDisplayName, checkType: 'absence' })
-
- await servers[0].blocklist.removeFromMyBlocklist({ token: userToken, account: 'root' })
- })
-
- it('Should not send a new mention notification if the remote account mention a local account', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- await waitJobs(servers)
- const { id: threadId } = await servers[1].comments.createThread({ videoId: uuid, text: '@user_1 hello' })
-
- await waitJobs(servers)
-
- const byAccountDisplayName = 'super root 2 name'
- await checkCommentMention({ ...baseParams, shortUUID, threadId, commentId: threadId, byAccountDisplayName, checkType: 'absence' })
- })
-
- it('Should send a new mention notification after local comments', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hellotext: 1' })
-
- await waitJobs(servers)
- await checkCommentMention({ ...baseParams, shortUUID, threadId, commentId: threadId, byAccountDisplayName, checkType: 'presence' })
-
- const { id: commentId } = await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: 'hello 2 @user_1' })
-
- await waitJobs(servers)
- await checkCommentMention({ ...baseParams, shortUUID, commentId, threadId, byAccountDisplayName, checkType: 'presence' })
- })
-
- it('Should send a new mention notification after remote comments', async function () {
- this.timeout(30000)
-
- const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- await waitJobs(servers)
-
- const text1 = `hello @user_1@${servers[0].host} 1`
- const { id: server2ThreadId } = await servers[1].comments.createThread({ videoId: uuid, text: text1 })
-
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: uuid })
- expect(data).to.have.lengthOf(1)
-
- const byAccountDisplayName = 'super root 2 name'
- const threadId = data[0].id
- await checkCommentMention({ ...baseParams, shortUUID, commentId: threadId, threadId, byAccountDisplayName, checkType: 'presence' })
-
- const text2 = `@user_1@${servers[0].host} hello 2 @root@${servers[0].host}`
- await servers[1].comments.addReply({ videoId: uuid, toCommentId: server2ThreadId, text: text2 })
-
- await waitJobs(servers)
-
- const tree = await servers[0].comments.getThread({ videoId: uuid, threadId })
-
- expect(tree.children).to.have.lengthOf(1)
- const commentId = tree.children[0].comment.id
-
- await checkCommentMention({ ...baseParams, shortUUID, commentId, threadId, byAccountDisplayName, checkType: 'presence' })
- })
-
- it('Should convert markdown in comment to html', async function () {
- this.timeout(30000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'super video' } })
-
- const { id: threadId } = await servers[0].comments.createThread({ videoId: uuid, text: '@user_1 hello 1' })
-
- await servers[0].comments.addReply({ videoId: uuid, toCommentId: threadId, text: '@user_1 ' + commentText })
-
- await waitJobs(servers)
-
- const latestEmail = emails[emails.length - 1]
- expect(latestEmail['html']).to.contain(expectedHtml)
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/notifications/index.ts b/server/tests/api/notifications/index.ts
deleted file mode 100644
index c0216b74f..000000000
--- a/server/tests/api/notifications/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import './admin-notifications'
-import './comments-notifications'
-import './moderation-notifications'
-import './notifications-api'
-import './registrations-notifications'
-import './user-notifications'
diff --git a/server/tests/api/notifications/moderation-notifications.ts b/server/tests/api/notifications/moderation-notifications.ts
deleted file mode 100644
index e7a5c47e9..000000000
--- a/server/tests/api/notifications/moderation-notifications.ts
+++ /dev/null
@@ -1,609 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import {
- checkAbuseStateChange,
- checkAutoInstanceFollowing,
- CheckerBaseParams,
- checkNewAbuseMessage,
- checkNewAccountAbuseForModerators,
- checkNewBlacklistOnMyVideo,
- checkNewCommentAbuseForModerators,
- checkNewInstanceFollower,
- checkNewVideoAbuseForModerators,
- checkNewVideoFromSubscription,
- checkVideoAutoBlacklistForModerators,
- checkVideoIsPublished,
- MockInstancesIndex,
- MockSmtpServer,
- prepareNotificationsTest
-} from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { buildUUID } from '@shared/extra-utils'
-import { AbuseState, CustomConfig, UserNotification, UserRole, VideoPrivacy } from '@shared/models'
-import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
-
-describe('Test moderation notifications', function () {
- let servers: PeerTubeServer[] = []
- let userToken1: string
- let userToken2: string
-
- let userNotifications: UserNotification[] = []
- let adminNotifications: UserNotification[] = []
- let adminNotificationsServer2: UserNotification[] = []
- let emails: object[] = []
-
- before(async function () {
- this.timeout(120000)
-
- const res = await prepareNotificationsTest(3)
- emails = res.emails
- userToken1 = res.userAccessToken
- servers = res.servers
- userNotifications = res.userNotifications
- adminNotifications = res.adminNotifications
- adminNotificationsServer2 = res.adminNotificationsServer2
-
- userToken2 = await servers[1].users.generateUserAndToken('user2', UserRole.USER)
- })
-
- describe('Abuse for moderators notification', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: adminNotifications,
- token: servers[0].accessToken
- }
- })
-
- it('Should not send a notification to moderators on local abuse reported by an admin', async function () {
- this.timeout(50000)
-
- const name = 'video for abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await servers[0].abuses.report({ videoId: video.id, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewVideoAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'absence' })
- })
-
- it('Should send a notification to moderators on local video abuse', async function () {
- this.timeout(50000)
-
- const name = 'video for abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await servers[0].abuses.report({ token: userToken1, videoId: video.id, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewVideoAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
- })
-
- it('Should send a notification to moderators on remote video abuse', async function () {
- this.timeout(50000)
-
- const name = 'video for abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await waitJobs(servers)
-
- const videoId = await servers[1].videos.getId({ uuid: video.uuid })
- await servers[1].abuses.report({ token: userToken2, videoId, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewVideoAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
- })
-
- it('Should send a notification to moderators on local comment abuse', async function () {
- this.timeout(50000)
-
- const name = 'video for abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
- const comment = await servers[0].comments.createThread({
- token: userToken1,
- videoId: video.id,
- text: 'comment abuse ' + buildUUID()
- })
-
- await waitJobs(servers)
-
- await servers[0].abuses.report({ token: userToken1, commentId: comment.id, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewCommentAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
- })
-
- it('Should send a notification to moderators on remote comment abuse', async function () {
- this.timeout(50000)
-
- const name = 'video for abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await servers[0].comments.createThread({
- token: userToken1,
- videoId: video.id,
- text: 'comment abuse ' + buildUUID()
- })
-
- await waitJobs(servers)
-
- const { data } = await servers[1].comments.listThreads({ videoId: video.uuid })
- const commentId = data[0].id
- await servers[1].abuses.report({ token: userToken2, commentId, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewCommentAbuseForModerators({ ...baseParams, shortUUID: video.shortUUID, videoName: name, checkType: 'presence' })
- })
-
- it('Should send a notification to moderators on local account abuse', async function () {
- this.timeout(50000)
-
- const username = 'user' + new Date().getTime()
- const { account } = await servers[0].users.create({ username, password: 'donald' })
- const accountId = account.id
-
- await servers[0].abuses.report({ token: userToken1, accountId, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewAccountAbuseForModerators({ ...baseParams, displayName: username, checkType: 'presence' })
- })
-
- it('Should send a notification to moderators on remote account abuse', async function () {
- this.timeout(50000)
-
- const username = 'user' + new Date().getTime()
- const tmpToken = await servers[0].users.generateUserAndToken(username)
- await servers[0].videos.upload({ token: tmpToken, attributes: { name: 'super video' } })
-
- await waitJobs(servers)
-
- const account = await servers[1].accounts.get({ accountName: username + '@' + servers[0].host })
- await servers[1].abuses.report({ token: userToken2, accountId: account.id, reason: 'super reason' })
-
- await waitJobs(servers)
- await checkNewAccountAbuseForModerators({ ...baseParams, displayName: username, checkType: 'presence' })
- })
- })
-
- describe('Abuse state change notification', function () {
- let baseParams: CheckerBaseParams
- let abuseId: number
-
- before(async function () {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken1
- }
-
- const name = 'abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- const body = await servers[0].abuses.report({ token: userToken1, videoId: video.id, reason: 'super reason' })
- abuseId = body.abuse.id
- })
-
- it('Should send a notification to reporter if the abuse has been accepted', async function () {
- this.timeout(30000)
-
- await servers[0].abuses.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
- await waitJobs(servers)
-
- await checkAbuseStateChange({ ...baseParams, abuseId, state: AbuseState.ACCEPTED, checkType: 'presence' })
- })
-
- it('Should send a notification to reporter if the abuse has been rejected', async function () {
- this.timeout(30000)
-
- await servers[0].abuses.update({ abuseId, body: { state: AbuseState.REJECTED } })
- await waitJobs(servers)
-
- await checkAbuseStateChange({ ...baseParams, abuseId, state: AbuseState.REJECTED, checkType: 'presence' })
- })
- })
-
- describe('New abuse message notification', function () {
- let baseParamsUser: CheckerBaseParams
- let baseParamsAdmin: CheckerBaseParams
- let abuseId: number
- let abuseId2: number
-
- before(async function () {
- baseParamsUser = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken1
- }
-
- baseParamsAdmin = {
- server: servers[0],
- emails,
- socketNotifications: adminNotifications,
- token: servers[0].accessToken
- }
-
- const name = 'abuse ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- {
- const body = await servers[0].abuses.report({ token: userToken1, videoId: video.id, reason: 'super reason' })
- abuseId = body.abuse.id
- }
-
- {
- const body = await servers[0].abuses.report({ token: userToken1, videoId: video.id, reason: 'super reason 2' })
- abuseId2 = body.abuse.id
- }
- })
-
- it('Should send a notification to reporter on new message', async function () {
- this.timeout(30000)
-
- const message = 'my super message to users'
- await servers[0].abuses.addMessage({ abuseId, message })
- await waitJobs(servers)
-
- await checkNewAbuseMessage({ ...baseParamsUser, abuseId, message, toEmail: 'user_1@example.com', checkType: 'presence' })
- })
-
- it('Should not send a notification to the admin if sent by the admin', async function () {
- this.timeout(30000)
-
- const message = 'my super message that should not be sent to the admin'
- await servers[0].abuses.addMessage({ abuseId, message })
- await waitJobs(servers)
-
- const toEmail = 'admin' + servers[0].internalServerNumber + '@example.com'
- await checkNewAbuseMessage({ ...baseParamsAdmin, abuseId, message, toEmail, checkType: 'absence' })
- })
-
- it('Should send a notification to moderators', async function () {
- this.timeout(30000)
-
- const message = 'my super message to moderators'
- await servers[0].abuses.addMessage({ token: userToken1, abuseId: abuseId2, message })
- await waitJobs(servers)
-
- const toEmail = 'admin' + servers[0].internalServerNumber + '@example.com'
- await checkNewAbuseMessage({ ...baseParamsAdmin, abuseId: abuseId2, message, toEmail, checkType: 'presence' })
- })
-
- it('Should not send a notification to reporter if sent by the reporter', async function () {
- this.timeout(30000)
-
- const message = 'my super message that should not be sent to reporter'
- await servers[0].abuses.addMessage({ token: userToken1, abuseId: abuseId2, message })
- await waitJobs(servers)
-
- const toEmail = 'user_1@example.com'
- await checkNewAbuseMessage({ ...baseParamsUser, abuseId: abuseId2, message, toEmail, checkType: 'absence' })
- })
- })
-
- describe('Video blacklist on my video', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken1
- }
- })
-
- it('Should send a notification to video owner on blacklist', async function () {
- this.timeout(30000)
-
- const name = 'video for abuse ' + buildUUID()
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await servers[0].blacklist.add({ videoId: uuid })
-
- await waitJobs(servers)
- await checkNewBlacklistOnMyVideo({ ...baseParams, shortUUID, videoName: name, blacklistType: 'blacklist' })
- })
-
- it('Should send a notification to video owner on unblacklist', async function () {
- this.timeout(30000)
-
- const name = 'video for abuse ' + buildUUID()
- const { uuid, shortUUID } = await servers[0].videos.upload({ token: userToken1, attributes: { name } })
-
- await servers[0].blacklist.add({ videoId: uuid })
-
- await waitJobs(servers)
- await servers[0].blacklist.remove({ videoId: uuid })
- await waitJobs(servers)
-
- await wait(500)
- await checkNewBlacklistOnMyVideo({ ...baseParams, shortUUID, videoName: name, blacklistType: 'unblacklist' })
- })
- })
-
- describe('New instance follows', function () {
- const instanceIndexServer = new MockInstancesIndex()
- let config: any
- let baseParams: CheckerBaseParams
-
- before(async function () {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: adminNotifications,
- token: servers[0].accessToken
- }
-
- const port = await instanceIndexServer.initialize()
- instanceIndexServer.addInstance(servers[1].host)
-
- config = {
- followings: {
- instance: {
- autoFollowIndex: {
- indexUrl: `http://127.0.0.1:${port}/api/v1/instances/hosts`,
- enabled: true
- }
- }
- }
- }
- })
-
- it('Should send a notification only to admin when there is a new instance follower', async function () {
- this.timeout(60000)
-
- await servers[2].follows.follow({ hosts: [ servers[0].url ] })
-
- await waitJobs(servers)
-
- await checkNewInstanceFollower({ ...baseParams, followerHost: servers[2].host, checkType: 'presence' })
-
- const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
- await checkNewInstanceFollower({ ...baseParams, ...userOverride, followerHost: servers[2].host, checkType: 'absence' })
- })
-
- it('Should send a notification on auto follow back', async function () {
- this.timeout(40000)
-
- await servers[2].follows.unfollow({ target: servers[0] })
- await waitJobs(servers)
-
- const config = {
- followings: {
- instance: {
- autoFollowBack: { enabled: true }
- }
- }
- }
- await servers[0].config.updateCustomSubConfig({ newConfig: config })
-
- await servers[2].follows.follow({ hosts: [ servers[0].url ] })
-
- await waitJobs(servers)
-
- const followerHost = servers[0].host
- const followingHost = servers[2].host
- await checkAutoInstanceFollowing({ ...baseParams, followerHost, followingHost, checkType: 'presence' })
-
- const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
- await checkAutoInstanceFollowing({ ...baseParams, ...userOverride, followerHost, followingHost, checkType: 'absence' })
-
- config.followings.instance.autoFollowBack.enabled = false
- await servers[0].config.updateCustomSubConfig({ newConfig: config })
- await servers[0].follows.unfollow({ target: servers[2] })
- await servers[2].follows.unfollow({ target: servers[0] })
- })
-
- it('Should send a notification on auto instances index follow', async function () {
- this.timeout(30000)
- await servers[0].follows.unfollow({ target: servers[1] })
-
- await servers[0].config.updateCustomSubConfig({ newConfig: config })
-
- await wait(5000)
- await waitJobs(servers)
-
- const followerHost = servers[0].host
- const followingHost = servers[1].host
- await checkAutoInstanceFollowing({ ...baseParams, followerHost, followingHost, checkType: 'presence' })
-
- config.followings.instance.autoFollowIndex.enabled = false
- await servers[0].config.updateCustomSubConfig({ newConfig: config })
- await servers[0].follows.unfollow({ target: servers[1] })
- })
- })
-
- describe('Video-related notifications when video auto-blacklist is enabled', function () {
- let userBaseParams: CheckerBaseParams
- let adminBaseParamsServer1: CheckerBaseParams
- let adminBaseParamsServer2: CheckerBaseParams
- let uuid: string
- let shortUUID: string
- let videoName: string
- let currentCustomConfig: CustomConfig
-
- before(async function () {
-
- adminBaseParamsServer1 = {
- server: servers[0],
- emails,
- socketNotifications: adminNotifications,
- token: servers[0].accessToken
- }
-
- adminBaseParamsServer2 = {
- server: servers[1],
- emails,
- socketNotifications: adminNotificationsServer2,
- token: servers[1].accessToken
- }
-
- userBaseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userToken1
- }
-
- currentCustomConfig = await servers[0].config.getCustomConfig()
-
- const autoBlacklistTestsCustomConfig = {
- ...currentCustomConfig,
-
- autoBlacklist: {
- videos: {
- ofUsers: {
- enabled: true
- }
- }
- }
- }
-
- // enable transcoding otherwise own publish notification after transcoding not expected
- autoBlacklistTestsCustomConfig.transcoding.enabled = true
- await servers[0].config.updateCustomConfig({ newCustomConfig: autoBlacklistTestsCustomConfig })
-
- await servers[0].subscriptions.add({ targetUri: 'user_1_channel@' + servers[0].host })
- await servers[1].subscriptions.add({ targetUri: 'user_1_channel@' + servers[0].host })
- })
-
- it('Should send notification to moderators on new video with auto-blacklist', async function () {
- this.timeout(120000)
-
- videoName = 'video with auto-blacklist ' + buildUUID()
- const video = await servers[0].videos.upload({ token: userToken1, attributes: { name: videoName } })
- shortUUID = video.shortUUID
- uuid = video.uuid
-
- await waitJobs(servers)
- await checkVideoAutoBlacklistForModerators({ ...adminBaseParamsServer1, shortUUID, videoName, checkType: 'presence' })
- })
-
- it('Should not send video publish notification if auto-blacklisted', async function () {
- this.timeout(120000)
-
- await checkVideoIsPublished({ ...userBaseParams, videoName, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send a local user subscription notification if auto-blacklisted', async function () {
- this.timeout(120000)
-
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send a remote user subscription notification if auto-blacklisted', async function () {
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName, shortUUID, checkType: 'absence' })
- })
-
- it('Should send video published and unblacklist after video unblacklisted', async function () {
- this.timeout(120000)
-
- await servers[0].blacklist.remove({ videoId: uuid })
-
- await waitJobs(servers)
-
- // FIXME: Can't test as two notifications sent to same user and util only checks last one
- // One notification might be better anyways
- // await checkNewBlacklistOnMyVideo(userBaseParams, videoUUID, videoName, 'unblacklist')
- // await checkVideoIsPublished(userBaseParams, videoName, videoUUID, 'presence')
- })
-
- it('Should send a local user subscription notification after removed from blacklist', async function () {
- this.timeout(120000)
-
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a remote user subscription notification after removed from blacklist', async function () {
- this.timeout(120000)
-
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName, shortUUID, checkType: 'presence' })
- })
-
- it('Should send unblacklist but not published/subscription notes after unblacklisted if scheduled update pending', async function () {
- this.timeout(120000)
-
- const updateAt = new Date(new Date().getTime() + 1000000)
-
- const name = 'video with auto-blacklist and future schedule ' + buildUUID()
-
- const attributes = {
- name,
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
-
- const { shortUUID, uuid } = await servers[0].videos.upload({ token: userToken1, attributes })
-
- await servers[0].blacklist.remove({ videoId: uuid })
-
- await waitJobs(servers)
- await checkNewBlacklistOnMyVideo({ ...userBaseParams, shortUUID, videoName: name, blacklistType: 'unblacklist' })
-
- // FIXME: Can't test absence as two notifications sent to same user and util only checks last one
- // One notification might be better anyways
- // await checkVideoIsPublished(userBaseParams, name, uuid, 'absence')
-
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName: name, shortUUID, checkType: 'absence' })
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send publish/subscription notifications after scheduled update if video still auto-blacklisted', async function () {
- this.timeout(120000)
-
- // In 2 seconds
- const updateAt = new Date(new Date().getTime() + 2000)
-
- const name = 'video with schedule done and still auto-blacklisted ' + buildUUID()
-
- const attributes = {
- name,
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
-
- const { shortUUID } = await servers[0].videos.upload({ token: userToken1, attributes })
-
- await wait(6000)
- await checkVideoIsPublished({ ...userBaseParams, videoName: name, shortUUID, checkType: 'absence' })
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer1, videoName: name, shortUUID, checkType: 'absence' })
- await checkNewVideoFromSubscription({ ...adminBaseParamsServer2, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send a notification to moderators on new video without auto-blacklist', async function () {
- this.timeout(120000)
-
- const name = 'video without auto-blacklist ' + buildUUID()
-
- // admin with blacklist right will not be auto-blacklisted
- const { shortUUID } = await servers[0].videos.upload({ attributes: { name } })
-
- await waitJobs(servers)
- await checkVideoAutoBlacklistForModerators({ ...adminBaseParamsServer1, shortUUID, videoName: name, checkType: 'absence' })
- })
-
- after(async () => {
- await servers[0].config.updateCustomConfig({ newCustomConfig: currentCustomConfig })
-
- await servers[0].subscriptions.remove({ uri: 'user_1_channel@' + servers[0].host })
- await servers[1].subscriptions.remove({ uri: 'user_1_channel@' + servers[0].host })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/notifications/notifications-api.ts b/server/tests/api/notifications/notifications-api.ts
deleted file mode 100644
index 1fc861160..000000000
--- a/server/tests/api/notifications/notifications-api.ts
+++ /dev/null
@@ -1,206 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- CheckerBaseParams,
- checkNewVideoFromSubscription,
- getAllNotificationsSettings,
- MockSmtpServer,
- prepareNotificationsTest
-} from '@server/tests/shared'
-import { UserNotification, UserNotificationSettingValue } from '@shared/models'
-import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
-
-describe('Test notifications API', function () {
- let server: PeerTubeServer
- let userNotifications: UserNotification[] = []
- let userToken: string
- let emails: object[] = []
-
- before(async function () {
- this.timeout(120000)
-
- const res = await prepareNotificationsTest(1)
- emails = res.emails
- userToken = res.userAccessToken
- userNotifications = res.userNotifications
- server = res.servers[0]
-
- await server.subscriptions.add({ token: userToken, targetUri: 'root_channel@' + server.host })
-
- for (let i = 0; i < 10; i++) {
- await server.videos.randomUpload({ wait: false })
- }
-
- await waitJobs([ server ])
- })
-
- describe('Notification list & count', function () {
-
- it('Should correctly list notifications', async function () {
- const { data, total } = await server.notifications.list({ token: userToken, start: 0, count: 2 })
-
- expect(data).to.have.lengthOf(2)
- expect(total).to.equal(10)
- })
- })
-
- describe('Mark as read', function () {
-
- it('Should mark as read some notifications', async function () {
- const { data } = await server.notifications.list({ token: userToken, start: 2, count: 3 })
- const ids = data.map(n => n.id)
-
- await server.notifications.markAsRead({ token: userToken, ids })
- })
-
- it('Should have the notifications marked as read', async function () {
- const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10 })
-
- expect(data[0].read).to.be.false
- expect(data[1].read).to.be.false
- expect(data[2].read).to.be.true
- expect(data[3].read).to.be.true
- expect(data[4].read).to.be.true
- expect(data[5].read).to.be.false
- })
-
- it('Should only list read notifications', async function () {
- const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: false })
-
- for (const notification of data) {
- expect(notification.read).to.be.true
- }
- })
-
- it('Should only list unread notifications', async function () {
- const { data } = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: true })
-
- for (const notification of data) {
- expect(notification.read).to.be.false
- }
- })
-
- it('Should mark as read all notifications', async function () {
- await server.notifications.markAsReadAll({ token: userToken })
-
- const body = await server.notifications.list({ token: userToken, start: 0, count: 10, unread: true })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
- })
-
- describe('Notification settings', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server,
- emails,
- socketNotifications: userNotifications,
- token: userToken
- }
- })
-
- it('Should not have notifications', async function () {
- this.timeout(20000)
-
- await server.notifications.updateMySettings({
- token: userToken,
- settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.NONE }
- })
-
- {
- const info = await server.users.getMyInfo({ token: userToken })
- expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.NONE)
- }
-
- const { name, shortUUID } = await server.videos.randomUpload()
-
- const check = { web: true, mail: true }
- await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should only have web notifications', async function () {
- this.timeout(20000)
-
- await server.notifications.updateMySettings({
- token: userToken,
- settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.WEB }
- })
-
- {
- const info = await server.users.getMyInfo({ token: userToken })
- expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.WEB)
- }
-
- const { name, shortUUID } = await server.videos.randomUpload()
-
- {
- const check = { mail: true, web: false }
- await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
- }
-
- {
- const check = { mail: false, web: true }
- await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'presence' })
- }
- })
-
- it('Should only have mail notifications', async function () {
- this.timeout(20000)
-
- await server.notifications.updateMySettings({
- token: userToken,
- settings: { ...getAllNotificationsSettings(), newVideoFromSubscription: UserNotificationSettingValue.EMAIL }
- })
-
- {
- const info = await server.users.getMyInfo({ token: userToken })
- expect(info.notificationSettings.newVideoFromSubscription).to.equal(UserNotificationSettingValue.EMAIL)
- }
-
- const { name, shortUUID } = await server.videos.randomUpload()
-
- {
- const check = { mail: false, web: true }
- await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'absence' })
- }
-
- {
- const check = { mail: true, web: false }
- await checkNewVideoFromSubscription({ ...baseParams, check, videoName: name, shortUUID, checkType: 'presence' })
- }
- })
-
- it('Should have email and web notifications', async function () {
- this.timeout(20000)
-
- await server.notifications.updateMySettings({
- token: userToken,
- settings: {
- ...getAllNotificationsSettings(),
- newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
- }
- })
-
- {
- const info = await server.users.getMyInfo({ token: userToken })
- expect(info.notificationSettings.newVideoFromSubscription).to.equal(
- UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
- )
- }
-
- const { name, shortUUID } = await server.videos.randomUpload()
-
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/notifications/registrations-notifications.ts b/server/tests/api/notifications/registrations-notifications.ts
deleted file mode 100644
index d20fc8df3..000000000
--- a/server/tests/api/notifications/registrations-notifications.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import {
- CheckerBaseParams,
- checkRegistrationRequest,
- checkUserRegistered,
- MockSmtpServer,
- prepareNotificationsTest
-} from '@server/tests/shared'
-import { UserNotification } from '@shared/models'
-import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
-
-describe('Test registrations notifications', function () {
- let server: PeerTubeServer
- let userToken1: string
-
- let userNotifications: UserNotification[] = []
- let adminNotifications: UserNotification[] = []
- let emails: object[] = []
-
- let baseParams: CheckerBaseParams
-
- before(async function () {
- this.timeout(120000)
-
- const res = await prepareNotificationsTest(1)
-
- server = res.servers[0]
- emails = res.emails
- userToken1 = res.userAccessToken
- adminNotifications = res.adminNotifications
- userNotifications = res.userNotifications
-
- baseParams = {
- server,
- emails,
- socketNotifications: adminNotifications,
- token: server.accessToken
- }
- })
-
- describe('New direct registration for moderators', function () {
-
- before(async function () {
- await server.config.enableSignup(false)
- })
-
- it('Should send a notification only to moderators when a user registers on the instance', async function () {
- this.timeout(50000)
-
- await server.registrations.register({ username: 'user_10' })
-
- await waitJobs([ server ])
-
- await checkUserRegistered({ ...baseParams, username: 'user_10', checkType: 'presence' })
-
- const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
- await checkUserRegistered({ ...baseParams, ...userOverride, username: 'user_10', checkType: 'absence' })
- })
- })
-
- describe('New registration request for moderators', function () {
-
- before(async function () {
- await server.config.enableSignup(true)
- })
-
- it('Should send a notification on new registration request', async function () {
- this.timeout(50000)
-
- const registrationReason = 'my reason'
- await server.registrations.requestRegistration({ username: 'user_11', registrationReason })
-
- await waitJobs([ server ])
-
- await checkRegistrationRequest({ ...baseParams, username: 'user_11', registrationReason, checkType: 'presence' })
-
- const userOverride = { socketNotifications: userNotifications, token: userToken1, check: { web: true, mail: false } }
- await checkRegistrationRequest({ ...baseParams, ...userOverride, username: 'user_11', registrationReason, checkType: 'absence' })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/notifications/user-notifications.ts b/server/tests/api/notifications/user-notifications.ts
deleted file mode 100644
index 55da10265..000000000
--- a/server/tests/api/notifications/user-notifications.ts
+++ /dev/null
@@ -1,574 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- CheckerBaseParams,
- checkMyVideoImportIsFinished,
- checkNewActorFollow,
- checkNewVideoFromSubscription,
- checkVideoIsPublished,
- checkVideoStudioEditionIsFinished,
- FIXTURE_URLS,
- MockSmtpServer,
- prepareNotificationsTest,
- uploadRandomVideoOnServers
-} from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { buildUUID } from '@shared/extra-utils'
-import { UserNotification, UserNotificationType, VideoPrivacy, VideoStudioTask } from '@shared/models'
-import { cleanupTests, findExternalSavedVideo, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
-
-describe('Test user notifications', function () {
- let servers: PeerTubeServer[] = []
- let userAccessToken: string
-
- let userNotifications: UserNotification[] = []
- let adminNotifications: UserNotification[] = []
- let adminNotificationsServer2: UserNotification[] = []
- let emails: object[] = []
-
- let channelId: number
-
- before(async function () {
- this.timeout(120000)
-
- const res = await prepareNotificationsTest(3)
- emails = res.emails
- userAccessToken = res.userAccessToken
- servers = res.servers
- userNotifications = res.userNotifications
- adminNotifications = res.adminNotifications
- adminNotificationsServer2 = res.adminNotificationsServer2
- channelId = res.channelId
- })
-
- describe('New video from my subscription notification', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userAccessToken
- }
- })
-
- it('Should not send notifications if the user does not follow the video publisher', async function () {
- this.timeout(50000)
-
- await uploadRandomVideoOnServers(servers, 1)
-
- const notification = await servers[0].notifications.getLatest({ token: userAccessToken })
- expect(notification).to.be.undefined
-
- expect(emails).to.have.lengthOf(0)
- expect(userNotifications).to.have.lengthOf(0)
- })
-
- it('Should send a new video notification if the user follows the local video publisher', async function () {
- this.timeout(15000)
-
- await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@' + servers[0].host })
- await waitJobs(servers)
-
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a new video notification from a remote account', async function () {
- this.timeout(150000) // Server 2 has transcoding enabled
-
- await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@' + servers[1].host })
- await waitJobs(servers)
-
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a new video notification on a scheduled publication', async function () {
- this.timeout(50000)
-
- // In 2 seconds
- const updateAt = new Date(new Date().getTime() + 2000)
-
- const data = {
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
-
- await wait(6000)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a new video notification on a remote scheduled publication', async function () {
- this.timeout(100000)
-
- // In 2 seconds
- const updateAt = new Date(new Date().getTime() + 2000)
-
- const data = {
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
- await waitJobs(servers)
-
- await wait(6000)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should not send a notification before the video is published', async function () {
- this.timeout(150000)
-
- const updateAt = new Date(new Date().getTime() + 1000000)
-
- const data = {
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
-
- await wait(6000)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should send a new video notification when a video becomes public', async function () {
- this.timeout(50000)
-
- const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
-
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
-
- await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
-
- await waitJobs(servers)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a new video notification when a remote video becomes public', async function () {
- this.timeout(120000)
-
- const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
-
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
-
- await servers[1].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
-
- await waitJobs(servers)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should not send a new video notification when a video becomes unlisted', async function () {
- this.timeout(50000)
-
- const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 1, data)
-
- await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
-
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send a new video notification when a remote video becomes unlisted', async function () {
- this.timeout(100000)
-
- const data = { privacy: VideoPrivacy.PRIVATE }
- const { name, uuid, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
-
- await servers[1].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
-
- await waitJobs(servers)
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should send a new video notification after a video import', async function () {
- this.timeout(100000)
-
- const name = 'video import ' + buildUUID()
-
- const attributes = {
- name,
- channelId,
- privacy: VideoPrivacy.PUBLIC,
- targetUrl: FIXTURE_URLS.goodVideo
- }
- const { video } = await servers[0].imports.importVideo({ attributes })
-
- await waitJobs(servers)
-
- await checkNewVideoFromSubscription({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
- })
- })
-
- describe('My video is published', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[1],
- emails,
- socketNotifications: adminNotificationsServer2,
- token: servers[1].accessToken
- }
- })
-
- it('Should not send a notification if transcoding is not enabled', async function () {
- this.timeout(50000)
-
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 1)
- await waitJobs(servers)
-
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- })
-
- it('Should not send a notification if the wait transcoding is false', async function () {
- this.timeout(100_000)
-
- await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: false })
- await waitJobs(servers)
-
- const notification = await servers[0].notifications.getLatest({ token: userAccessToken })
- if (notification) {
- expect(notification.type).to.not.equal(UserNotificationType.MY_VIDEO_PUBLISHED)
- }
- })
-
- it('Should send a notification even if the video is not transcoded in other resolutions', async function () {
- this.timeout(100_000)
-
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true, fixture: 'video_short_240p.mp4' })
- await waitJobs(servers)
-
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a notification with a transcoded video', async function () {
- this.timeout(100_000)
-
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
- await waitJobs(servers)
-
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should send a notification when an imported video is transcoded', async function () {
- this.timeout(120000)
-
- const name = 'video import ' + buildUUID()
-
- const attributes = {
- name,
- channelId,
- privacy: VideoPrivacy.PUBLIC,
- targetUrl: FIXTURE_URLS.goodVideo,
- waitTranscoding: true
- }
- const { video } = await servers[1].imports.importVideo({ attributes })
-
- await waitJobs(servers)
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID: video.shortUUID, checkType: 'presence' })
- })
-
- it('Should send a notification when the scheduled update has been proceeded', async function () {
- this.timeout(70000)
-
- // In 2 seconds
- const updateAt = new Date(new Date().getTime() + 2000)
-
- const data = {
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
-
- await wait(6000)
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
-
- it('Should not send a notification before the video is published', async function () {
- this.timeout(150000)
-
- const updateAt = new Date(new Date().getTime() + 1000000)
-
- const data = {
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: updateAt.toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
- const { name, shortUUID } = await uploadRandomVideoOnServers(servers, 2, data)
-
- await wait(6000)
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'absence' })
- })
- })
-
- describe('My live replay is published', function () {
-
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[1],
- emails,
- socketNotifications: adminNotificationsServer2,
- token: servers[1].accessToken
- }
- })
-
- it('Should send a notification is a live replay of a non permanent live is published', async function () {
- this.timeout(120000)
-
- const { shortUUID } = await servers[1].live.create({
- fields: {
- name: 'non permanent live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[1].store.channel.id,
- saveReplay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC },
- permanentLive: false
- }
- })
-
- const ffmpegCommand = await servers[1].live.sendRTMPStreamInVideo({ videoId: shortUUID })
-
- await waitJobs(servers)
- await servers[1].live.waitUntilPublished({ videoId: shortUUID })
-
- await stopFfmpeg(ffmpegCommand)
- await servers[1].live.waitUntilReplacedByReplay({ videoId: shortUUID })
-
- await waitJobs(servers)
- await checkVideoIsPublished({ ...baseParams, videoName: 'non permanent live', shortUUID, checkType: 'presence' })
- })
-
- it('Should send a notification is a live replay of a permanent live is published', async function () {
- this.timeout(120000)
-
- const { shortUUID } = await servers[1].live.create({
- fields: {
- name: 'permanent live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[1].store.channel.id,
- saveReplay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC },
- permanentLive: true
- }
- })
-
- const ffmpegCommand = await servers[1].live.sendRTMPStreamInVideo({ videoId: shortUUID })
-
- await waitJobs(servers)
- await servers[1].live.waitUntilPublished({ videoId: shortUUID })
-
- const liveDetails = await servers[1].videos.get({ id: shortUUID })
-
- await stopFfmpeg(ffmpegCommand)
-
- await servers[1].live.waitUntilWaiting({ videoId: shortUUID })
- await waitJobs(servers)
-
- const video = await findExternalSavedVideo(servers[1], liveDetails)
- expect(video).to.exist
-
- await checkVideoIsPublished({ ...baseParams, videoName: video.name, shortUUID: video.shortUUID, checkType: 'presence' })
- })
- })
-
- describe('Video studio', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[1],
- emails,
- socketNotifications: adminNotificationsServer2,
- token: servers[1].accessToken
- }
- })
-
- it('Should send a notification after studio edition', async function () {
- this.timeout(240000)
-
- const { name, shortUUID, id } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
-
- await waitJobs(servers)
- await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
-
- const tasks: VideoStudioTask[] = [
- {
- name: 'cut',
- options: {
- start: 0,
- end: 1
- }
- }
- ]
- await servers[1].videoStudio.createEditionTasks({ videoId: id, tasks })
- await waitJobs(servers)
-
- await checkVideoStudioEditionIsFinished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
- })
- })
-
- describe('My video is imported', function () {
- let baseParams: CheckerBaseParams
-
- before(() => {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: adminNotifications,
- token: servers[0].accessToken
- }
- })
-
- it('Should send a notification when the video import failed', async function () {
- this.timeout(70000)
-
- const name = 'video import ' + buildUUID()
-
- const attributes = {
- name,
- channelId,
- privacy: VideoPrivacy.PRIVATE,
- targetUrl: FIXTURE_URLS.badVideo
- }
- const { video: { shortUUID } } = await servers[0].imports.importVideo({ attributes })
-
- await waitJobs(servers)
-
- const url = FIXTURE_URLS.badVideo
- await checkMyVideoImportIsFinished({ ...baseParams, videoName: name, shortUUID, url, success: false, checkType: 'presence' })
- })
-
- it('Should send a notification when the video import succeeded', async function () {
- this.timeout(70000)
-
- const name = 'video import ' + buildUUID()
-
- const attributes = {
- name,
- channelId,
- privacy: VideoPrivacy.PRIVATE,
- targetUrl: FIXTURE_URLS.goodVideo
- }
- const { video: { shortUUID } } = await servers[0].imports.importVideo({ attributes })
-
- await waitJobs(servers)
-
- const url = FIXTURE_URLS.goodVideo
- await checkMyVideoImportIsFinished({ ...baseParams, videoName: name, shortUUID, url, success: true, checkType: 'presence' })
- })
- })
-
- describe('New actor follow', function () {
- let baseParams: CheckerBaseParams
- const myChannelName = 'super channel name'
- const myUserName = 'super user name'
-
- before(async function () {
- baseParams = {
- server: servers[0],
- emails,
- socketNotifications: userNotifications,
- token: userAccessToken
- }
-
- await servers[0].users.updateMe({ displayName: 'super root name' })
-
- await servers[0].users.updateMe({
- token: userAccessToken,
- displayName: myUserName
- })
-
- await servers[1].users.updateMe({ displayName: 'super root 2 name' })
-
- await servers[0].channels.update({
- token: userAccessToken,
- channelName: 'user_1_channel',
- attributes: { displayName: myChannelName }
- })
- })
-
- it('Should notify when a local channel is following one of our channel', async function () {
- this.timeout(50000)
-
- await servers[0].subscriptions.add({ targetUri: 'user_1_channel@' + servers[0].host })
- await waitJobs(servers)
-
- await checkNewActorFollow({
- ...baseParams,
- followType: 'channel',
- followerName: 'root',
- followerDisplayName: 'super root name',
- followingDisplayName: myChannelName,
- checkType: 'presence'
- })
-
- await servers[0].subscriptions.remove({ uri: 'user_1_channel@' + servers[0].host })
- })
-
- it('Should notify when a remote channel is following one of our channel', async function () {
- this.timeout(50000)
-
- await servers[1].subscriptions.add({ targetUri: 'user_1_channel@' + servers[0].host })
- await waitJobs(servers)
-
- await checkNewActorFollow({
- ...baseParams,
- followType: 'channel',
- followerName: 'root',
- followerDisplayName: 'super root 2 name',
- followingDisplayName: myChannelName,
- checkType: 'presence'
- })
-
- await servers[1].subscriptions.remove({ uri: 'user_1_channel@' + servers[0].host })
- })
-
- // PeerTube does not support account -> account follows
- // it('Should notify when a local account is following one of our channel', async function () {
- // this.timeout(50000)
- //
- // await addUserSubscription(servers[0].url, servers[0].accessToken, 'user_1@' + servers[0].host)
- //
- // await waitJobs(servers)
- //
- // await checkNewActorFollow(baseParams, 'account', 'root', 'super root name', myUserName, 'presence')
- // })
-
- // it('Should notify when a remote account is following one of our channel', async function () {
- // this.timeout(50000)
- //
- // await addUserSubscription(servers[1].url, servers[1].accessToken, 'user_1@' + servers[0].host)
- //
- // await waitJobs(servers)
- //
- // await checkNewActorFollow(baseParams, 'account', 'root', 'super root 2 name', myUserName, 'presence')
- // })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/object-storage/index.ts b/server/tests/api/object-storage/index.ts
deleted file mode 100644
index 1f4489fa3..000000000
--- a/server/tests/api/object-storage/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './live'
-export * from './video-imports'
-export * from './video-static-file-privacy'
-export * from './videos'
diff --git a/server/tests/api/object-storage/live.ts b/server/tests/api/object-storage/live.ts
deleted file mode 100644
index 07ff4763b..000000000
--- a/server/tests/api/object-storage/live.ts
+++ /dev/null
@@ -1,311 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectStartWith, MockObjectStorageProxy, SQLCommand, testLiveVideoResolutions } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- findExternalSavedVideo,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs,
- waitUntilLivePublishedOnAllServers,
- waitUntilLiveReplacedByReplayOnAllServers,
- waitUntilLiveWaitingOnAllServers
-} from '@shared/server-commands'
-
-async function createLive (server: PeerTubeServer, permanent: boolean) {
- const attributes: LiveVideoCreate = {
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- name: 'my super live',
- saveReplay: true,
- replaySettings: { privacy: VideoPrivacy.PUBLIC },
- permanentLive: permanent
- }
-
- const { uuid } = await server.live.create({ fields: attributes })
-
- return uuid
-}
-
-async function checkFilesExist (options: {
- servers: PeerTubeServer[]
- videoUUID: string
- numberOfFiles: number
- objectStorage: ObjectStorageCommand
-}) {
- const { servers, videoUUID, numberOfFiles, objectStorage } = options
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.files).to.have.lengthOf(0)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const files = video.streamingPlaylists[0].files
- expect(files).to.have.lengthOf(numberOfFiles)
-
- for (const file of files) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-}
-
-async function checkFilesCleanup (options: {
- server: PeerTubeServer
- videoUUID: string
- resolutions: number[]
- objectStorage: ObjectStorageCommand
-}) {
- const { server, videoUUID, resolutions, objectStorage } = options
-
- const resolutionFiles = resolutions.map((_value, i) => `${i}.m3u8`)
-
- for (const playlistName of [ 'master.m3u8' ].concat(resolutionFiles)) {
- await server.live.getPlaylistFile({
- videoUUID,
- playlistName,
- expectedStatus: HttpStatusCode.NOT_FOUND_404,
- objectStorage
- })
- }
-
- await server.live.getSegmentFile({
- videoUUID,
- playlistNumber: 0,
- segment: 0,
- objectStorage,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
-}
-
-describe('Object storage for lives', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- let servers: PeerTubeServer[]
- let sqlCommandServer1: SQLCommand
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- await objectStorage.prepareDefaultMockBuckets()
- servers = await createMultipleServers(2, objectStorage.getDefaultMockConfig())
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableTranscoding()
-
- sqlCommandServer1 = new SQLCommand(servers[0])
- })
-
- describe('Without live transcoding', function () {
- let videoUUID: string
-
- before(async function () {
- await servers[0].config.enableLive({ transcoding: false })
-
- videoUUID = await createLive(servers[0], false)
- })
-
- it('Should create a live and publish it on object storage', async function () {
- this.timeout(220000)
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
- await waitUntilLivePublishedOnAllServers(servers, videoUUID)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: videoUUID,
- resolutions: [ 720 ],
- transcoded: false,
- objectStorage
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have saved the replay on object storage', async function () {
- this.timeout(220000)
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUID)
- await waitJobs(servers)
-
- await checkFilesExist({ servers, videoUUID, numberOfFiles: 1, objectStorage })
- })
-
- it('Should have cleaned up live files from object storage', async function () {
- await checkFilesCleanup({ server: servers[0], videoUUID, resolutions: [ 720 ], objectStorage })
- })
- })
-
- describe('With live transcoding', function () {
- const resolutions = [ 720, 480, 360, 240, 144 ]
-
- before(async function () {
- await servers[0].config.enableLive({ transcoding: true })
- })
-
- describe('Normal replay', function () {
- let videoUUIDNonPermanent: string
-
- before(async function () {
- videoUUIDNonPermanent = await createLive(servers[0], false)
- })
-
- it('Should create a live and publish it on object storage', async function () {
- this.timeout(240000)
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDNonPermanent })
- await waitUntilLivePublishedOnAllServers(servers, videoUUIDNonPermanent)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: videoUUIDNonPermanent,
- resolutions,
- transcoded: true,
- objectStorage
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have saved the replay on object storage', async function () {
- this.timeout(220000)
-
- await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUIDNonPermanent)
- await waitJobs(servers)
-
- await checkFilesExist({ servers, videoUUID: videoUUIDNonPermanent, numberOfFiles: 5, objectStorage })
- })
-
- it('Should have cleaned up live files from object storage', async function () {
- await checkFilesCleanup({ server: servers[0], videoUUID: videoUUIDNonPermanent, resolutions, objectStorage })
- })
- })
-
- describe('Permanent replay', function () {
- let videoUUIDPermanent: string
-
- before(async function () {
- videoUUIDPermanent = await createLive(servers[0], true)
- })
-
- it('Should create a live and publish it on object storage', async function () {
- this.timeout(240000)
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDPermanent })
- await waitUntilLivePublishedOnAllServers(servers, videoUUIDPermanent)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: videoUUIDPermanent,
- resolutions,
- transcoded: true,
- objectStorage
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have saved the replay on object storage', async function () {
- this.timeout(220000)
-
- await waitUntilLiveWaitingOnAllServers(servers, videoUUIDPermanent)
- await waitJobs(servers)
-
- const videoLiveDetails = await servers[0].videos.get({ id: videoUUIDPermanent })
- const replay = await findExternalSavedVideo(servers[0], videoLiveDetails)
-
- await checkFilesExist({ servers, videoUUID: replay.uuid, numberOfFiles: 5, objectStorage })
- })
-
- it('Should have cleaned up live files from object storage', async function () {
- await checkFilesCleanup({ server: servers[0], videoUUID: videoUUIDPermanent, resolutions, objectStorage })
- })
- })
- })
-
- describe('With object storage base url', function () {
- const mockObjectStorageProxy = new MockObjectStorageProxy()
- let baseMockUrl: string
-
- before(async function () {
- this.timeout(120000)
-
- const port = await mockObjectStorageProxy.initialize()
- const bucketName = objectStorage.getMockStreamingPlaylistsBucketName()
- baseMockUrl = `http://127.0.0.1:${port}/${bucketName}`
-
- await objectStorage.prepareDefaultMockBuckets()
-
- const config = {
- object_storage: {
- enabled: true,
- endpoint: 'http://' + ObjectStorageCommand.getMockEndpointHost(),
- region: ObjectStorageCommand.getMockRegion(),
-
- credentials: ObjectStorageCommand.getMockCredentialsConfig(),
-
- streaming_playlists: {
- bucket_name: bucketName,
- prefix: '',
- base_url: baseMockUrl
- }
- }
- }
-
- await servers[0].kill()
- await servers[0].run(config)
-
- await servers[0].config.enableLive({ transcoding: true, resolutions: 'min' })
- })
-
- it('Should publish a live and replace the base url', async function () {
- this.timeout(240000)
-
- const videoUUIDPermanent = await createLive(servers[0], true)
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDPermanent })
- await waitUntilLivePublishedOnAllServers(servers, videoUUIDPermanent)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: videoUUIDPermanent,
- resolutions: [ 720 ],
- transcoded: true,
- objectStorage,
- objectStorageBaseUrl: baseMockUrl
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
- })
-
- after(async function () {
- await sqlCommandServer1.cleanup()
- await objectStorage.cleanupMock()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/object-storage/video-imports.ts b/server/tests/api/object-storage/video-imports.ts
deleted file mode 100644
index 57150e5a6..000000000
--- a/server/tests/api/object-storage/video-imports.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectStartWith, FIXTURE_URLS } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-async function importVideo (server: PeerTubeServer) {
- const attributes = {
- name: 'import 2',
- privacy: VideoPrivacy.PUBLIC,
- channelId: server.store.channel.id,
- targetUrl: FIXTURE_URLS.goodVideo720
- }
-
- const { video: { uuid } } = await server.imports.importVideo({ attributes })
-
- return uuid
-}
-
-describe('Object storage for video import', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- let server: PeerTubeServer
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- await objectStorage.prepareDefaultMockBuckets()
-
- server = await createSingleServer(1, objectStorage.getDefaultMockConfig())
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableImports()
- })
-
- describe('Without transcoding', async function () {
-
- before(async function () {
- await server.config.disableTranscoding()
- })
-
- it('Should import a video and have sent it to object storage', async function () {
- this.timeout(120000)
-
- const uuid = await importVideo(server)
- await waitJobs(server)
-
- const video = await server.videos.get({ id: uuid })
-
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
-
- const fileUrl = video.files[0].fileUrl
- expectStartWith(fileUrl, objectStorage.getMockWebVideosBaseUrl())
-
- await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('With transcoding', async function () {
-
- before(async function () {
- await server.config.enableTranscoding()
- })
-
- it('Should import a video and have sent it to object storage', async function () {
- this.timeout(120000)
-
- const uuid = await importVideo(server)
- await waitJobs(server)
-
- const video = await server.videos.get({ id: uuid })
-
- expect(video.files).to.have.lengthOf(5)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
- expect(video.streamingPlaylists[0].files).to.have.lengthOf(5)
-
- for (const file of video.files) {
- expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- for (const file of video.streamingPlaylists[0].files) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/object-storage/video-static-file-privacy.ts b/server/tests/api/object-storage/video-static-file-privacy.ts
deleted file mode 100644
index 64ab542a5..000000000
--- a/server/tests/api/object-storage/video-static-file-privacy.ts
+++ /dev/null
@@ -1,570 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { basename } from 'path'
-import { checkVideoFileTokenReinjection, expectStartWith, SQLCommand } from '@server/tests/shared'
-import { areScalewayObjectStorageTestsDisabled, getAllFiles, getHLS } from '@shared/core-utils'
-import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- findExternalSavedVideo,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-function extractFilenameFromUrl (url: string) {
- const parts = basename(url).split(':')
-
- return parts[parts.length - 1]
-}
-
-describe('Object storage for video static file privacy', function () {
- // We need real world object storage to check ACL
- if (areScalewayObjectStorageTestsDisabled()) return
-
- let server: PeerTubeServer
- let sqlCommand: SQLCommand
- let userToken: string
-
- // ---------------------------------------------------------------------------
-
- async function checkPrivateVODFiles (uuid: string) {
- const video = await server.videos.getWithToken({ id: uuid })
-
- for (const file of video.files) {
- expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/web-videos/private/')
-
- await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- for (const file of getAllFiles(video)) {
- const internalFileUrl = await sqlCommand.getInternalFileUrl(file.id)
- expectStartWith(internalFileUrl, ObjectStorageCommand.getScalewayBaseUrl())
- await makeRawRequest({ url: internalFileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- }
-
- const hls = getHLS(video)
-
- if (hls) {
- for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
- expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
- }
-
- await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
-
- for (const file of hls.files) {
- expectStartWith(file.fileUrl, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- }
-
- async function checkPublicVODFiles (uuid: string) {
- const video = await server.videos.getWithToken({ id: uuid })
-
- for (const file of getAllFiles(video)) {
- expectStartWith(file.fileUrl, ObjectStorageCommand.getScalewayBaseUrl())
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const hls = getHLS(video)
-
- if (hls) {
- expectStartWith(hls.playlistUrl, ObjectStorageCommand.getScalewayBaseUrl())
- expectStartWith(hls.segmentsSha256Url, ObjectStorageCommand.getScalewayBaseUrl())
-
- await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- // ---------------------------------------------------------------------------
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1, ObjectStorageCommand.getDefaultScalewayConfig({ serverNumber: 1 }))
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableMinimumTranscoding()
-
- userToken = await server.users.generateUserAndToken('user1')
-
- sqlCommand = new SQLCommand(server)
- })
-
- describe('VOD', function () {
- let privateVideoUUID: string
- let publicVideoUUID: string
- let passwordProtectedVideoUUID: string
- let userPrivateVideoUUID: string
-
- const correctPassword = 'my super password'
- const correctPasswordHeader = { 'x-peertube-video-password': correctPassword }
- const incorrectPasswordHeader = { 'x-peertube-video-password': correctPassword + 'toto' }
-
- // ---------------------------------------------------------------------------
-
- async function getSampleFileUrls (videoId: string) {
- const video = await server.videos.getWithToken({ id: videoId })
-
- return {
- webVideoFile: video.files[0].fileUrl,
- hlsFile: getHLS(video).files[0].fileUrl
- }
- }
-
- // ---------------------------------------------------------------------------
-
- it('Should upload a private video and have appropriate object storage ACL', async function () {
- this.timeout(120000)
-
- {
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- privateVideoUUID = uuid
- }
-
- {
- const { uuid } = await server.videos.quickUpload({ name: 'user video', token: userToken, privacy: VideoPrivacy.PRIVATE })
- userPrivateVideoUUID = uuid
- }
-
- await waitJobs([ server ])
-
- await checkPrivateVODFiles(privateVideoUUID)
- })
-
- it('Should upload a password protected video and have appropriate object storage ACL', async function () {
- this.timeout(120000)
-
- {
- const { uuid } = await server.videos.quickUpload({
- name: 'video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ correctPassword ]
- })
- passwordProtectedVideoUUID = uuid
- }
- await waitJobs([ server ])
-
- await checkPrivateVODFiles(passwordProtectedVideoUUID)
- })
-
- it('Should upload a public video and have appropriate object storage ACL', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.UNLISTED })
- await waitJobs([ server ])
-
- publicVideoUUID = uuid
-
- await checkPublicVODFiles(publicVideoUUID)
- })
-
- it('Should not get files without appropriate OAuth token', async function () {
- this.timeout(60000)
-
- const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
-
- await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should not get files without appropriate password or appropriate OAuth token', async function () {
- this.timeout(60000)
-
- const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
-
- await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({
- url: webVideoFile,
- token: null,
- headers: incorrectPasswordHeader,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({
- url: webVideoFile,
- token: null,
- headers: correctPasswordHeader,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({
- url: hlsFile,
- token: null,
- headers: incorrectPasswordHeader,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({
- url: hlsFile,
- token: null,
- headers: correctPasswordHeader,
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should not get HLS file of another video', async function () {
- this.timeout(60000)
-
- const privateVideo = await server.videos.getWithToken({ id: privateVideoUUID })
- const hlsFilename = basename(getHLS(privateVideo).files[0].fileUrl)
-
- const badUrl = server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + userPrivateVideoUUID + '/' + hlsFilename
- const goodUrl = server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + privateVideoUUID + '/' + hlsFilename
-
- await makeRawRequest({ url: badUrl, token: server.accessToken, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- await makeRawRequest({ url: goodUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should correctly check OAuth, video file token of private video', async function () {
- this.timeout(60000)
-
- const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID })
- const goodVideoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID })
-
- const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
-
- for (const url of [ webVideoFile, hlsFile ]) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, query: { videoFileToken: badVideoFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: goodVideoFileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- }
- })
-
- it('Should correctly check OAuth, video file token or video password of password protected video', async function () {
- this.timeout(60000)
-
- const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID })
- const goodVideoFileToken = await server.videoToken.getVideoFileToken({
- videoId: passwordProtectedVideoUUID,
- videoPassword: correctPassword
- })
-
- const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
-
- for (const url of [ hlsFile, webVideoFile ]) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, query: { videoFileToken: badVideoFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: goodVideoFileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({
- url,
- headers: incorrectPasswordHeader,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- await makeRawRequest({ url, headers: correctPasswordHeader, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should reinject video file token', async function () {
- this.timeout(120000)
-
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID })
-
- await checkVideoFileTokenReinjection({
- server,
- videoUUID: privateVideoUUID,
- videoFileToken,
- resolutions: [ 240, 720 ],
- isLive: false
- })
- })
-
- it('Should update public video to private', async function () {
- this.timeout(60000)
-
- await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.INTERNAL } })
-
- await checkPrivateVODFiles(publicVideoUUID)
- })
-
- it('Should update private video to public', async function () {
- this.timeout(60000)
-
- await server.videos.update({ id: publicVideoUUID, attributes: { privacy: VideoPrivacy.PUBLIC } })
-
- await checkPublicVODFiles(publicVideoUUID)
- })
- })
-
- describe('Live', function () {
- let normalLiveId: string
- let normalLive: LiveVideo
-
- let permanentLiveId: string
- let permanentLive: LiveVideo
-
- let passwordProtectedLiveId: string
- let passwordProtectedLive: LiveVideo
-
- const correctPassword = 'my super password'
-
- let unrelatedFileToken: string
-
- // ---------------------------------------------------------------------------
-
- async function checkLiveFiles (live: LiveVideo, liveId: string, videoPassword?: string) {
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await server.live.waitUntilPublished({ videoId: liveId })
-
- const video = videoPassword
- ? await server.videos.getWithPassword({ id: liveId, password: videoPassword })
- : await server.videos.getWithToken({ id: liveId })
-
- const fileToken = videoPassword
- ? await server.videoToken.getVideoFileToken({ token: null, videoId: video.uuid, videoPassword })
- : await server.videoToken.getVideoFileToken({ videoId: video.uuid })
-
- const hls = video.streamingPlaylists[0]
-
- for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
- expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
- if (videoPassword) {
- await makeRawRequest({ url, headers: { 'x-peertube-video-password': videoPassword }, expectedStatus: HttpStatusCode.OK_200 })
- }
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- if (videoPassword) {
- await makeRawRequest({
- url,
- headers: { 'x-peertube-video-password': 'incorrectPassword' },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
- }
-
- await stopFfmpeg(ffmpegCommand)
- }
-
- async function checkReplay (replay: VideoDetails) {
- const fileToken = await server.videoToken.getVideoFileToken({ videoId: replay.uuid })
-
- const hls = replay.streamingPlaylists[0]
- expect(hls.files).to.not.have.lengthOf(0)
-
- for (const file of hls.files) {
- await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: file.fileUrl, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url: file.fileUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({
- url: file.fileUrl,
- query: { videoFileToken: unrelatedFileToken },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
-
- for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
- expectStartWith(url, server.url + '/object-storage-proxy/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- }
- }
-
- // ---------------------------------------------------------------------------
-
- before(async function () {
- await server.config.enableMinimumTranscoding()
-
- const { uuid } = await server.videos.quickUpload({ name: 'another video' })
- unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
-
- await server.config.enableLive({
- allowReplay: true,
- transcoding: true,
- resolutions: 'min'
- })
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: true,
- permanentLive: false,
- privacy: VideoPrivacy.PRIVATE
- })
- normalLiveId = video.uuid
- normalLive = live
- }
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: true,
- permanentLive: true,
- privacy: VideoPrivacy.PRIVATE
- })
- permanentLiveId = video.uuid
- permanentLive = live
- }
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: false,
- permanentLive: false,
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ correctPassword ]
- })
- passwordProtectedLiveId = video.uuid
- passwordProtectedLive = live
- }
- })
-
- it('Should create a private normal live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles(normalLive, normalLiveId)
- })
-
- it('Should create a private permanent live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles(permanentLive, permanentLiveId)
- })
-
- it('Should create a password protected live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles(passwordProtectedLive, passwordProtectedLiveId, correctPassword)
- })
-
- it('Should reinject video file token in permanent live', async function () {
- this.timeout(240000)
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: permanentLive.rtmpUrl, streamKey: permanentLive.streamKey })
- await server.live.waitUntilPublished({ videoId: permanentLiveId })
-
- const video = await server.videos.getWithToken({ id: permanentLiveId })
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid })
-
- await checkVideoFileTokenReinjection({
- server,
- videoUUID: permanentLiveId,
- videoFileToken,
- resolutions: [ 720 ],
- isLive: true
- })
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have created a replay of the normal live with a private static path', async function () {
- this.timeout(240000)
-
- await server.live.waitUntilReplacedByReplay({ videoId: normalLiveId })
-
- const replay = await server.videos.getWithToken({ id: normalLiveId })
- await checkReplay(replay)
- })
-
- it('Should have created a replay of the permanent live with a private static path', async function () {
- this.timeout(240000)
-
- await server.live.waitUntilWaiting({ videoId: permanentLiveId })
- await waitJobs([ server ])
-
- const live = await server.videos.getWithToken({ id: permanentLiveId })
- const replayFromList = await findExternalSavedVideo(server, live)
- const replay = await server.videos.getWithToken({ id: replayFromList.id })
-
- await checkReplay(replay)
- })
- })
-
- describe('With private files proxy disabled and public ACL for private files', function () {
- let videoUUID: string
-
- before(async function () {
- this.timeout(240000)
-
- await server.kill()
-
- const config = ObjectStorageCommand.getDefaultScalewayConfig({
- serverNumber: 1,
- enablePrivateProxy: false,
- privateACL: 'public-read'
- })
- await server.run(config)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- videoUUID = uuid
-
- await waitJobs([ server ])
- })
-
- it('Should display object storage path for a private video and be able to access them', async function () {
- this.timeout(60000)
-
- await checkPublicVODFiles(videoUUID)
- })
-
- it('Should not be able to access object storage proxy', async function () {
- const privateVideo = await server.videos.getWithToken({ id: videoUUID })
- const webVideoFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl)
- const hlsFilename = extractFilenameFromUrl(getHLS(privateVideo).files[0].fileUrl)
-
- await makeRawRequest({
- url: server.url + '/object-storage-proxy/web-videos/private/' + webVideoFilename,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeRawRequest({
- url: server.url + '/object-storage-proxy/streaming-playlists/hls/private/' + videoUUID + '/' + hlsFilename,
- token: server.accessToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
- })
-
- after(async function () {
- this.timeout(240000)
-
- const { data } = await server.videos.listAllForAdmin()
-
- for (const v of data) {
- await server.videos.remove({ id: v.uuid })
- }
-
- for (const v of data) {
- await server.servers.waitUntilLog('Removed files of video ' + v.url)
- }
-
- await sqlCommand.cleanup()
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/object-storage/videos.ts b/server/tests/api/object-storage/videos.ts
deleted file mode 100644
index dcc52ef06..000000000
--- a/server/tests/api/object-storage/videos.ts
+++ /dev/null
@@ -1,438 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import bytes from 'bytes'
-import { expect } from 'chai'
-import { stat } from 'fs-extra'
-import { merge } from 'lodash'
-import {
- checkTmpIsEmpty,
- checkWebTorrentWorks,
- expectLogDoesNotContain,
- expectStartWith,
- generateHighBitrateVideo,
- MockObjectStorageProxy,
- SQLCommand
-} from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { sha1 } from '@shared/extra-utils'
-import { HttpStatusCode, VideoDetails } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- createSingleServer,
- doubleFollow,
- killallServers,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkFiles (options: {
- server: PeerTubeServer
- originServer: PeerTubeServer
- originSQLCommand: SQLCommand
-
- video: VideoDetails
-
- baseMockUrl?: string
-
- playlistBucket: string
- playlistPrefix?: string
-
- webVideoBucket: string
- webVideoPrefix?: string
-}) {
- const {
- server,
- originServer,
- originSQLCommand,
- video,
- playlistBucket,
- webVideoBucket,
- baseMockUrl,
- playlistPrefix,
- webVideoPrefix
- } = options
-
- let allFiles = video.files
-
- for (const file of video.files) {
- const baseUrl = baseMockUrl
- ? `${baseMockUrl}/${webVideoBucket}/`
- : `http://${webVideoBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
-
- const prefix = webVideoPrefix || ''
- const start = baseUrl + prefix
-
- expectStartWith(file.fileUrl, start)
-
- const res = await makeRawRequest({ url: file.fileDownloadUrl, expectedStatus: HttpStatusCode.FOUND_302 })
- const location = res.headers['location']
- expectStartWith(location, start)
-
- await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const hls = video.streamingPlaylists[0]
-
- if (hls) {
- allFiles = allFiles.concat(hls.files)
-
- const baseUrl = baseMockUrl
- ? `${baseMockUrl}/${playlistBucket}/`
- : `http://${playlistBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
-
- const prefix = playlistPrefix || ''
- const start = baseUrl + prefix
-
- expectStartWith(hls.playlistUrl, start)
- expectStartWith(hls.segmentsSha256Url, start)
-
- await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- const resSha = await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
- expect(JSON.stringify(resSha.body)).to.not.throw
-
- let i = 0
- for (const file of hls.files) {
- expectStartWith(file.fileUrl, start)
-
- const res = await makeRawRequest({ url: file.fileDownloadUrl, expectedStatus: HttpStatusCode.FOUND_302 })
- const location = res.headers['location']
- expectStartWith(location, start)
-
- await makeRawRequest({ url: location, expectedStatus: HttpStatusCode.OK_200 })
-
- if (originServer.internalServerNumber === server.internalServerNumber) {
- const infohash = sha1(`${2 + hls.playlistUrl}+V${i}`)
- const dbInfohashes = await originSQLCommand.getPlaylistInfohash(hls.id)
-
- expect(dbInfohashes).to.include(infohash)
- }
-
- i++
- }
- }
-
- for (const file of allFiles) {
- await checkWebTorrentWorks(file.magnetUri)
-
- const res = await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.have.length.above(100)
- }
-
- return allFiles.map(f => f.fileUrl)
-}
-
-function runTestSuite (options: {
- fixture?: string
-
- maxUploadPart?: string
-
- playlistBucket: string
- playlistPrefix?: string
-
- webVideoBucket: string
- webVideoPrefix?: string
-
- useMockBaseUrl?: boolean
-}) {
- const mockObjectStorageProxy = new MockObjectStorageProxy()
- const { fixture } = options
- let baseMockUrl: string
-
- let servers: PeerTubeServer[]
- let sqlCommands: SQLCommand[] = []
- const objectStorage = new ObjectStorageCommand()
-
- let keptUrls: string[] = []
-
- const uuidsToDelete: string[] = []
- let deletedUrls: string[] = []
-
- before(async function () {
- this.timeout(240000)
-
- const port = await mockObjectStorageProxy.initialize()
- baseMockUrl = options.useMockBaseUrl
- ? `http://127.0.0.1:${port}`
- : undefined
-
- await objectStorage.createMockBucket(options.playlistBucket)
- await objectStorage.createMockBucket(options.webVideoBucket)
-
- const config = {
- object_storage: {
- enabled: true,
- endpoint: 'http://' + ObjectStorageCommand.getMockEndpointHost(),
- region: ObjectStorageCommand.getMockRegion(),
-
- credentials: ObjectStorageCommand.getMockCredentialsConfig(),
-
- max_upload_part: options.maxUploadPart || '5MB',
-
- streaming_playlists: {
- bucket_name: options.playlistBucket,
- prefix: options.playlistPrefix,
- base_url: baseMockUrl
- ? `${baseMockUrl}/${options.playlistBucket}`
- : undefined
- },
-
- web_videos: {
- bucket_name: options.webVideoBucket,
- prefix: options.webVideoPrefix,
- base_url: baseMockUrl
- ? `${baseMockUrl}/${options.webVideoBucket}`
- : undefined
- }
- }
- }
-
- servers = await createMultipleServers(2, config)
-
- await setAccessTokensToServers(servers)
- await doubleFollow(servers[0], servers[1])
-
- for (const server of servers) {
- const { uuid } = await server.videos.quickUpload({ name: 'video to keep' })
- await waitJobs(servers)
-
- const files = await server.videos.listFiles({ id: uuid })
- keptUrls = keptUrls.concat(files.map(f => f.fileUrl))
- }
-
- sqlCommands = servers.map(s => new SQLCommand(s))
- })
-
- it('Should upload a video and move it to the object storage without transcoding', async function () {
- this.timeout(40000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1', fixture })
- uuidsToDelete.push(uuid)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
- const files = await checkFiles({ ...options, server, originServer: servers[0], originSQLCommand: sqlCommands[0], video, baseMockUrl })
-
- deletedUrls = deletedUrls.concat(files)
- }
- })
-
- it('Should upload a video and move it to the object storage with transcoding', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[1].videos.quickUpload({ name: 'video 2', fixture })
- uuidsToDelete.push(uuid)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
- const files = await checkFiles({ ...options, server, originServer: servers[0], originSQLCommand: sqlCommands[0], video, baseMockUrl })
-
- deletedUrls = deletedUrls.concat(files)
- }
- })
-
- it('Should fetch correctly all the files', async function () {
- for (const url of deletedUrls.concat(keptUrls)) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should correctly delete the files', async function () {
- await servers[0].videos.remove({ id: uuidsToDelete[0] })
- await servers[1].videos.remove({ id: uuidsToDelete[1] })
-
- await waitJobs(servers)
-
- for (const url of deletedUrls) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
-
- it('Should have kept other files', async function () {
- for (const url of keptUrls) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should have an empty tmp directory', async function () {
- for (const server of servers) {
- await checkTmpIsEmpty(server)
- }
- })
-
- it('Should not have downloaded files from object storage', async function () {
- for (const server of servers) {
- await expectLogDoesNotContain(server, 'from object storage')
- }
- })
-
- after(async function () {
- await mockObjectStorageProxy.terminate()
- await objectStorage.cleanupMock()
-
- for (const sqlCommand of sqlCommands) {
- await sqlCommand.cleanup()
- }
-
- await cleanupTests(servers)
- })
-}
-
-describe('Object storage for videos', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- describe('Test config', function () {
- let server: PeerTubeServer
-
- const baseConfig = objectStorage.getDefaultMockConfig()
-
- const badCredentials = {
- access_key_id: 'AKIAIOSFODNN7EXAMPLE',
- secret_access_key: 'aJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
- }
-
- it('Should fail with same bucket names without prefix', function (done) {
- const config = merge({}, baseConfig, {
- object_storage: {
- streaming_playlists: {
- bucket_name: 'aaa'
- },
-
- web_videos: {
- bucket_name: 'aaa'
- }
- }
- })
-
- createSingleServer(1, config)
- .then(() => done(new Error('Did not throw')))
- .catch(() => done())
- })
-
- it('Should fail with bad credentials', async function () {
- this.timeout(60000)
-
- await objectStorage.prepareDefaultMockBuckets()
-
- const config = merge({}, baseConfig, {
- object_storage: {
- credentials: badCredentials
- }
- })
-
- server = await createSingleServer(1, config)
- await setAccessTokensToServers([ server ])
-
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
-
- await waitJobs([ server ], { skipDelayed: true })
- const video = await server.videos.get({ id: uuid })
-
- expectStartWith(video.files[0].fileUrl, server.url)
-
- await killallServers([ server ])
- })
-
- it('Should succeed with credentials from env', async function () {
- this.timeout(60000)
-
- await objectStorage.prepareDefaultMockBuckets()
-
- const config = merge({}, baseConfig, {
- object_storage: {
- credentials: {
- access_key_id: '',
- secret_access_key: ''
- }
- }
- })
-
- const goodCredentials = ObjectStorageCommand.getMockCredentialsConfig()
-
- server = await createSingleServer(1, config, {
- env: {
- AWS_ACCESS_KEY_ID: goodCredentials.access_key_id,
- AWS_SECRET_ACCESS_KEY: goodCredentials.secret_access_key
- }
- })
-
- await setAccessTokensToServers([ server ])
-
- const { uuid } = await server.videos.quickUpload({ name: 'video' })
-
- await waitJobs([ server ], { skipDelayed: true })
- const video = await server.videos.get({ id: uuid })
-
- expectStartWith(video.files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
-
- await cleanupTests([ server ])
- })
- })
-
- describe('Test simple object storage', function () {
- runTestSuite({
- playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
- webVideoBucket: objectStorage.getMockBucketName('web-videos')
- })
- })
-
- describe('Test object storage with prefix', function () {
- runTestSuite({
- playlistBucket: objectStorage.getMockBucketName('mybucket'),
- webVideoBucket: objectStorage.getMockBucketName('mybucket'),
-
- playlistPrefix: 'streaming-playlists_',
- webVideoPrefix: 'webvideo_'
- })
- })
-
- describe('Test object storage with prefix and base URL', function () {
- runTestSuite({
- playlistBucket: objectStorage.getMockBucketName('mybucket'),
- webVideoBucket: objectStorage.getMockBucketName('mybucket'),
-
- playlistPrefix: 'streaming-playlists/',
- webVideoPrefix: 'webvideo/',
-
- useMockBaseUrl: true
- })
- })
-
- describe('Test object storage with file bigger than upload part', function () {
- let fixture: string
- const maxUploadPart = '5MB'
-
- before(async function () {
- this.timeout(120000)
-
- fixture = await generateHighBitrateVideo()
-
- const { size } = await stat(fixture)
-
- if (bytes.parse(maxUploadPart) > size) {
- throw Error(`Fixture file is too small (${size}) to make sense for this test.`)
- }
- })
-
- runTestSuite({
- maxUploadPart,
- playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
- webVideoBucket: objectStorage.getMockBucketName('web-videos'),
- fixture
- })
- })
-})
diff --git a/server/tests/api/redundancy/index.ts b/server/tests/api/redundancy/index.ts
deleted file mode 100644
index 37dc3f88c..000000000
--- a/server/tests/api/redundancy/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import './redundancy-constraints'
-import './redundancy'
-import './manage-redundancy'
diff --git a/server/tests/api/redundancy/manage-redundancy.ts b/server/tests/api/redundancy/manage-redundancy.ts
deleted file mode 100644
index 404b65a99..000000000
--- a/server/tests/api/redundancy/manage-redundancy.ts
+++ /dev/null
@@ -1,324 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- RedundancyCommand,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { VideoPrivacy, VideoRedundanciesTarget } from '@shared/models'
-
-describe('Test manage videos redundancy', function () {
- const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]
-
- let servers: PeerTubeServer[]
- let video1Server2UUID: string
- let video2Server2UUID: string
- let redundanciesToRemove: number[] = []
-
- let commands: RedundancyCommand[]
-
- before(async function () {
- this.timeout(120000)
-
- const config = {
- transcoding: {
- hls: {
- enabled: true
- }
- },
- redundancy: {
- videos: {
- check_interval: '1 second',
- strategies: [
- {
- strategy: 'recently-added',
- min_lifetime: '1 hour',
- size: '10MB',
- min_views: 0
- }
- ]
- }
- }
- }
- servers = await createMultipleServers(3, config)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- commands = servers.map(s => s.redundancy)
-
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
- video1Server2UUID = uuid
- }
-
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2' } })
- video2Server2UUID = uuid
- }
-
- await waitJobs(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- await doubleFollow(servers[0], servers[2])
- await commands[0].updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
-
- await waitJobs(servers)
- })
-
- it('Should not have redundancies on server 3', async function () {
- for (const target of targets) {
- const body = await commands[2].listVideos({ target })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should correctly list followings by redundancy', async function () {
- const body = await servers[0].follows.getFollowings({ sort: '-redundancyAllowed' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- expect(body.data[0].following.host).to.equal(servers[1].host)
- expect(body.data[1].following.host).to.equal(servers[2].host)
- })
-
- it('Should not have "remote-videos" redundancies on server 2', async function () {
- this.timeout(120000)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 10)
- await waitJobs(servers)
-
- const body = await commands[1].listVideos({ target: 'remote-videos' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should have "my-videos" redundancies on server 2', async function () {
- this.timeout(120000)
-
- const body = await commands[1].listVideos({ target: 'my-videos' })
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
-
- const videos1 = videos.find(v => v.uuid === video1Server2UUID)
- const videos2 = videos.find(v => v.uuid === video2Server2UUID)
-
- expect(videos1.name).to.equal('video 1 server 2')
- expect(videos2.name).to.equal('video 2 server 2')
-
- expect(videos1.redundancies.files).to.have.lengthOf(4)
- expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
-
- const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
-
- for (const r of redundancies) {
- expect(r.strategy).to.be.null
- expect(r.fileUrl).to.exist
- expect(r.createdAt).to.exist
- expect(r.updatedAt).to.exist
- expect(r.expiresOn).to.exist
- }
- })
-
- it('Should not have "my-videos" redundancies on server 1', async function () {
- const body = await commands[0].listVideos({ target: 'my-videos' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should have "remote-videos" redundancies on server 1', async function () {
- this.timeout(120000)
-
- const body = await commands[0].listVideos({ target: 'remote-videos' })
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
-
- const videos1 = videos.find(v => v.uuid === video1Server2UUID)
- const videos2 = videos.find(v => v.uuid === video2Server2UUID)
-
- expect(videos1.name).to.equal('video 1 server 2')
- expect(videos2.name).to.equal('video 2 server 2')
-
- expect(videos1.redundancies.files).to.have.lengthOf(4)
- expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
-
- const redundancies = videos1.redundancies.files.concat(videos1.redundancies.streamingPlaylists)
-
- for (const r of redundancies) {
- expect(r.strategy).to.equal('recently-added')
- expect(r.fileUrl).to.exist
- expect(r.createdAt).to.exist
- expect(r.updatedAt).to.exist
- expect(r.expiresOn).to.exist
- }
- })
-
- it('Should correctly paginate and sort results', async function () {
- {
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: 'name',
- start: 0,
- count: 2
- })
-
- const videos = body.data
- expect(videos[0].name).to.equal('video 1 server 2')
- expect(videos[1].name).to.equal('video 2 server 2')
- }
-
- {
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: '-name',
- start: 0,
- count: 2
- })
-
- const videos = body.data
- expect(videos[0].name).to.equal('video 2 server 2')
- expect(videos[1].name).to.equal('video 1 server 2')
- }
-
- {
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: '-name',
- start: 1,
- count: 1
- })
-
- expect(body.data[0].name).to.equal('video 1 server 2')
- }
- })
-
- it('Should manually add a redundancy and list it', async function () {
- this.timeout(120000)
-
- const uuid = (await servers[1].videos.quickUpload({ name: 'video 3 server 2', privacy: VideoPrivacy.UNLISTED })).uuid
- await waitJobs(servers)
- const videoId = await servers[0].videos.getId({ uuid })
-
- await commands[0].addVideo({ videoId })
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 15)
- await waitJobs(servers)
-
- {
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: '-name',
- start: 0,
- count: 5
- })
-
- const video = body.data[0]
-
- expect(video.name).to.equal('video 3 server 2')
- expect(video.redundancies.files).to.have.lengthOf(4)
- expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
-
- const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
-
- for (const r of redundancies) {
- redundanciesToRemove.push(r.id)
-
- expect(r.strategy).to.equal('manual')
- expect(r.fileUrl).to.exist
- expect(r.createdAt).to.exist
- expect(r.updatedAt).to.exist
- expect(r.expiresOn).to.be.null
- }
- }
-
- const body = await commands[1].listVideos({
- target: 'my-videos',
- sort: '-name',
- start: 0,
- count: 5
- })
-
- const video = body.data[0]
- expect(video.name).to.equal('video 3 server 2')
- expect(video.redundancies.files).to.have.lengthOf(4)
- expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
-
- const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
-
- for (const r of redundancies) {
- expect(r.strategy).to.be.null
- expect(r.fileUrl).to.exist
- expect(r.createdAt).to.exist
- expect(r.updatedAt).to.exist
- expect(r.expiresOn).to.be.null
- }
- })
-
- it('Should manually remove a redundancy and remove it from the list', async function () {
- this.timeout(120000)
-
- for (const redundancyId of redundanciesToRemove) {
- await commands[0].removeVideo({ redundancyId })
- }
-
- {
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: '-name',
- start: 0,
- count: 5
- })
-
- const videos = body.data
-
- expect(videos).to.have.lengthOf(2)
-
- const video = videos[0]
- expect(video.name).to.equal('video 2 server 2')
- expect(video.redundancies.files).to.have.lengthOf(4)
- expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
-
- const redundancies = video.redundancies.files.concat(video.redundancies.streamingPlaylists)
-
- redundanciesToRemove = redundancies.map(r => r.id)
- }
- })
-
- it('Should remove another (auto) redundancy', async function () {
- for (const redundancyId of redundanciesToRemove) {
- await commands[0].removeVideo({ redundancyId })
- }
-
- const body = await commands[0].listVideos({
- target: 'remote-videos',
- sort: '-name',
- start: 0,
- count: 5
- })
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('video 1 server 2')
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/redundancy/redundancy-constraints.ts b/server/tests/api/redundancy/redundancy-constraints.ts
deleted file mode 100644
index c86573168..000000000
--- a/server/tests/api/redundancy/redundancy-constraints.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test redundancy constraints', function () {
- let remoteServer: PeerTubeServer
- let localServer: PeerTubeServer
- let servers: PeerTubeServer[]
-
- const remoteServerConfig = {
- redundancy: {
- videos: {
- check_interval: '1 second',
- strategies: [
- {
- strategy: 'recently-added',
- min_lifetime: '1 hour',
- size: '100MB',
- min_views: 0
- }
- ]
- }
- }
- }
-
- async function uploadWrapper (videoName: string) {
- // Wait for transcoding
- const { id } = await localServer.videos.upload({ attributes: { name: 'to transcode', privacy: VideoPrivacy.PRIVATE } })
- await waitJobs([ localServer ])
-
- // Update video to schedule a federation
- await localServer.videos.update({ id, attributes: { name: videoName, privacy: VideoPrivacy.PUBLIC } })
- }
-
- async function getTotalRedundanciesLocalServer () {
- const body = await localServer.redundancy.listVideos({ target: 'my-videos' })
-
- return body.total
- }
-
- async function getTotalRedundanciesRemoteServer () {
- const body = await remoteServer.redundancy.listVideos({ target: 'remote-videos' })
-
- return body.total
- }
-
- before(async function () {
- this.timeout(120000)
-
- {
- remoteServer = await createSingleServer(1, remoteServerConfig)
- }
-
- {
- const config = {
- remote_redundancy: {
- videos: {
- accept_from: 'nobody'
- }
- }
- }
- localServer = await createSingleServer(2, config)
- }
-
- servers = [ remoteServer, localServer ]
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- await localServer.videos.upload({ attributes: { name: 'video 1 server 2' } })
-
- await waitJobs(servers)
-
- // Server 1 and server 2 follow each other
- await remoteServer.follows.follow({ hosts: [ localServer.url ] })
- await waitJobs(servers)
- await remoteServer.redundancy.updateRedundancy({ host: localServer.host, redundancyAllowed: true })
-
- await waitJobs(servers)
- })
-
- it('Should have redundancy on server 1 but not on server 2 with a nobody filter', async function () {
- this.timeout(120000)
-
- await waitJobs(servers)
- await remoteServer.servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- {
- const total = await getTotalRedundanciesRemoteServer()
- expect(total).to.equal(1)
- }
-
- {
- const total = await getTotalRedundanciesLocalServer()
- expect(total).to.equal(0)
- }
- })
-
- it('Should have redundancy on server 1 and on server 2 with an anybody filter', async function () {
- this.timeout(120000)
-
- const config = {
- remote_redundancy: {
- videos: {
- accept_from: 'anybody'
- }
- }
- }
- await killallServers([ localServer ])
- await localServer.run(config)
-
- await uploadWrapper('video 2 server 2')
-
- await remoteServer.servers.waitUntilLog('Duplicated ', 10)
- await waitJobs(servers)
-
- {
- const total = await getTotalRedundanciesRemoteServer()
- expect(total).to.equal(2)
- }
-
- {
- const total = await getTotalRedundanciesLocalServer()
- expect(total).to.equal(1)
- }
- })
-
- it('Should have redundancy on server 1 but not on server 2 with a followings filter', async function () {
- this.timeout(120000)
-
- const config = {
- remote_redundancy: {
- videos: {
- accept_from: 'followings'
- }
- }
- }
- await killallServers([ localServer ])
- await localServer.run(config)
-
- await uploadWrapper('video 3 server 2')
-
- await remoteServer.servers.waitUntilLog('Duplicated ', 15)
- await waitJobs(servers)
-
- {
- const total = await getTotalRedundanciesRemoteServer()
- expect(total).to.equal(3)
- }
-
- {
- const total = await getTotalRedundanciesLocalServer()
- expect(total).to.equal(1)
- }
- })
-
- it('Should have redundancy on server 1 and on server 2 with followings filter now server 2 follows server 1', async function () {
- this.timeout(120000)
-
- await localServer.follows.follow({ hosts: [ remoteServer.url ] })
- await waitJobs(servers)
-
- await uploadWrapper('video 4 server 2')
- await remoteServer.servers.waitUntilLog('Duplicated ', 20)
- await waitJobs(servers)
-
- {
- const total = await getTotalRedundanciesRemoteServer()
- expect(total).to.equal(4)
- }
-
- {
- const total = await getTotalRedundanciesLocalServer()
- expect(total).to.equal(2)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts
deleted file mode 100644
index 0c5c27225..000000000
--- a/server/tests/api/redundancy/redundancy.ts
+++ /dev/null
@@ -1,742 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readdir } from 'fs-extra'
-import { decode as magnetUriDecode } from 'magnet-uri'
-import { basename, join } from 'path'
-import { checkSegmentHash, checkVideoFilesWereRemoved, saveVideoInServers } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import {
- HttpStatusCode,
- VideoDetails,
- VideoFile,
- VideoPrivacy,
- VideoRedundancyStrategy,
- VideoRedundancyStrategyWithManual
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- makeRawRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-let servers: PeerTubeServer[] = []
-let video1Server2: VideoDetails
-
-async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], server: PeerTubeServer) {
- const parsed = magnetUriDecode(file.magnetUri)
-
- for (const ws of baseWebseeds) {
- const found = parsed.urlList.find(url => url === `${ws}${basename(file.fileUrl)}`)
- expect(found, `Webseed ${ws} not found in ${file.magnetUri} on server ${server.url}`).to.not.be.undefined
- }
-
- expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
-
- for (const url of parsed.urlList) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- }
-}
-
-async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebVideo = true) {
- const strategies: any[] = []
-
- if (strategy !== null) {
- strategies.push(
- {
- min_lifetime: '1 hour',
- strategy,
- size: '400KB',
-
- ...additionalParams
- }
- )
- }
-
- const config = {
- transcoding: {
- web_videos: {
- enabled: withWebVideo
- },
- hls: {
- enabled: true
- }
- },
- redundancy: {
- videos: {
- check_interval: '5 seconds',
- strategies
- }
- }
- }
-
- servers = await createMultipleServers(3, config)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- {
- const { id } = await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
- video1Server2 = await servers[1].videos.get({ id })
-
- await servers[1].views.simulateView({ id })
- }
-
- await waitJobs(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- // Server 1 and server 3 follow each other
- await doubleFollow(servers[0], servers[2])
- // Server 2 and server 3 follow each other
- await doubleFollow(servers[1], servers[2])
-
- await waitJobs(servers)
-}
-
-async function ensureSameFilenames (videoUUID: string) {
- let webVideoFilenames: string[]
- let hlsFilenames: string[]
-
- for (const server of servers) {
- const video = await server.videos.getWithToken({ id: videoUUID })
-
- // Ensure we use the same filenames that the origin
-
- const localWebVideoFilenames = video.files.map(f => basename(f.fileUrl)).sort()
- const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
-
- if (webVideoFilenames) expect(webVideoFilenames).to.deep.equal(localWebVideoFilenames)
- else webVideoFilenames = localWebVideoFilenames
-
- if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
- else hlsFilenames = localHLSFilenames
- }
-
- return { webVideoFilenames, hlsFilenames }
-}
-
-async function check1WebSeed (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2.uuid
-
- const webseeds = [
- `${servers[1].url}/static/web-videos/`
- ]
-
- for (const server of servers) {
- // With token to avoid issues with video follow constraints
- const video = await server.videos.getWithToken({ id: videoUUID })
-
- for (const f of video.files) {
- await checkMagnetWebseeds(f, webseeds, server)
- }
- }
-
- await ensureSameFilenames(videoUUID)
-}
-
-async function check2Webseeds (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2.uuid
-
- const webseeds = [
- `${servers[0].url}/static/redundancy/`,
- `${servers[1].url}/static/web-videos/`
- ]
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- for (const file of video.files) {
- await checkMagnetWebseeds(file, webseeds, server)
- }
- }
-
- const { webVideoFilenames } = await ensureSameFilenames(videoUUID)
-
- const directories = [
- servers[0].getDirectoryPath('redundancy'),
- servers[1].getDirectoryPath('web-videos')
- ]
-
- for (const directory of directories) {
- const files = await readdir(directory)
- expect(files).to.have.length.at.least(4)
-
- // Ensure we files exist on disk
- expect(files.find(f => webVideoFilenames.includes(f))).to.exist
- }
-}
-
-async function check0PlaylistRedundancies (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2.uuid
-
- for (const server of servers) {
- // With token to avoid issues with video follow constraints
- const video = await server.videos.getWithToken({ id: videoUUID })
-
- expect(video.streamingPlaylists).to.be.an('array')
- expect(video.streamingPlaylists).to.have.lengthOf(1)
- expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(0)
- }
-
- await ensureSameFilenames(videoUUID)
-}
-
-async function check1PlaylistRedundancies (videoUUID?: string) {
- if (!videoUUID) videoUUID = video1Server2.uuid
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.streamingPlaylists).to.have.lengthOf(1)
- expect(video.streamingPlaylists[0].redundancies).to.have.lengthOf(1)
-
- const redundancy = video.streamingPlaylists[0].redundancies[0]
-
- expect(redundancy.baseUrl).to.equal(servers[0].url + '/static/redundancy/hls/' + videoUUID)
- }
-
- const baseUrlPlaylist = servers[1].url + '/static/streaming-playlists/hls/' + videoUUID
- const baseUrlSegment = servers[0].url + '/static/redundancy/hls/' + videoUUID
-
- const video = await servers[0].videos.get({ id: videoUUID })
- const hlsPlaylist = video.streamingPlaylists[0]
-
- for (const resolution of [ 240, 360, 480, 720 ]) {
- await checkSegmentHash({ server: servers[1], baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist })
- }
-
- const { hlsFilenames } = await ensureSameFilenames(videoUUID)
-
- const directories = [
- servers[0].getDirectoryPath('redundancy/hls'),
- servers[1].getDirectoryPath('streaming-playlists/hls')
- ]
-
- for (const directory of directories) {
- const files = await readdir(join(directory, videoUUID))
- expect(files).to.have.length.at.least(4)
-
- // Ensure we files exist on disk
- expect(files.find(f => hlsFilenames.includes(f))).to.exist
- }
-}
-
-async function checkStatsGlobal (strategy: VideoRedundancyStrategyWithManual) {
- let totalSize: number = null
- let statsLength = 1
-
- if (strategy !== 'manual') {
- totalSize = 409600
- statsLength = 2
- }
-
- const data = await servers[0].stats.get()
- expect(data.videosRedundancy).to.have.lengthOf(statsLength)
-
- const stat = data.videosRedundancy[0]
- expect(stat.strategy).to.equal(strategy)
- expect(stat.totalSize).to.equal(totalSize)
-
- return stat
-}
-
-async function checkStatsWith1Redundancy (strategy: VideoRedundancyStrategyWithManual, onlyHls = false) {
- const stat = await checkStatsGlobal(strategy)
-
- expect(stat.totalUsed).to.be.at.least(1).and.below(409601)
- expect(stat.totalVideoFiles).to.equal(onlyHls ? 4 : 8)
- expect(stat.totalVideos).to.equal(1)
-}
-
-async function checkStatsWithoutRedundancy (strategy: VideoRedundancyStrategyWithManual) {
- const stat = await checkStatsGlobal(strategy)
-
- expect(stat.totalUsed).to.equal(0)
- expect(stat.totalVideoFiles).to.equal(0)
- expect(stat.totalVideos).to.equal(0)
-}
-
-async function findServerFollows () {
- const body = await servers[0].follows.getFollowings({ start: 0, count: 5, sort: '-createdAt' })
- const follows = body.data
- const server2 = follows.find(f => f.following.host === `${servers[1].host}`)
- const server3 = follows.find(f => f.following.host === `${servers[2].host}`)
-
- return { server2, server3 }
-}
-
-async function enableRedundancyOnServer1 () {
- await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: true })
-
- const { server2, server3 } = await findServerFollows()
-
- expect(server3).to.not.be.undefined
- expect(server3.following.hostRedundancyAllowed).to.be.false
-
- expect(server2).to.not.be.undefined
- expect(server2.following.hostRedundancyAllowed).to.be.true
-}
-
-async function disableRedundancyOnServer1 () {
- await servers[0].redundancy.updateRedundancy({ host: servers[1].host, redundancyAllowed: false })
-
- const { server2, server3 } = await findServerFollows()
-
- expect(server3).to.not.be.undefined
- expect(server3.following.hostRedundancyAllowed).to.be.false
-
- expect(server2).to.not.be.undefined
- expect(server2.following.hostRedundancyAllowed).to.be.false
-}
-
-describe('Test videos redundancy', function () {
-
- describe('With most-views strategy', function () {
- const strategy = 'most-views'
-
- before(function () {
- this.timeout(240000)
-
- return createServers(strategy)
- })
-
- it('Should have 1 webseed on the first video', async function () {
- await check1WebSeed()
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy(strategy)
- })
-
- it('Should enable redundancy on server 1', function () {
- return enableRedundancyOnServer1()
- })
-
- it('Should have 2 webseeds on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy)
- })
-
- it('Should undo redundancy on server 1 and remove duplicated videos', async function () {
- this.timeout(80000)
-
- await disableRedundancyOnServer1()
-
- await waitJobs(servers)
- await wait(5000)
-
- await check1WebSeed()
- await check0PlaylistRedundancies()
-
- await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
- })
-
- after(async function () {
- return cleanupTests(servers)
- })
- })
-
- describe('With trending strategy', function () {
- const strategy = 'trending'
-
- before(function () {
- this.timeout(240000)
-
- return createServers(strategy)
- })
-
- it('Should have 1 webseed on the first video', async function () {
- await check1WebSeed()
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy(strategy)
- })
-
- it('Should enable redundancy on server 1', function () {
- return enableRedundancyOnServer1()
- })
-
- it('Should have 2 webseeds on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy)
- })
-
- it('Should unfollow server 3 and keep duplicated videos', async function () {
- this.timeout(80000)
-
- await servers[0].follows.unfollow({ target: servers[2] })
-
- await waitJobs(servers)
- await wait(5000)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy)
- })
-
- it('Should unfollow server 2 and remove duplicated videos', async function () {
- this.timeout(80000)
-
- await servers[0].follows.unfollow({ target: servers[1] })
-
- await waitJobs(servers)
- await wait(5000)
-
- await check1WebSeed()
- await check0PlaylistRedundancies()
-
- await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('With recently added strategy', function () {
- const strategy = 'recently-added'
-
- before(function () {
- this.timeout(240000)
-
- return createServers(strategy, { min_views: 3 })
- })
-
- it('Should have 1 webseed on the first video', async function () {
- await check1WebSeed()
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy(strategy)
- })
-
- it('Should enable redundancy on server 1', function () {
- return enableRedundancyOnServer1()
- })
-
- it('Should still have 1 webseed on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await wait(15000)
- await waitJobs(servers)
-
- await check1WebSeed()
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy(strategy)
- })
-
- it('Should view 2 times the first video to have > min_views config', async function () {
- this.timeout(80000)
-
- await servers[0].views.simulateView({ id: video1Server2.uuid })
- await servers[2].views.simulateView({ id: video1Server2.uuid })
-
- await wait(10000)
- await waitJobs(servers)
- })
-
- it('Should have 2 webseeds on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy)
- })
-
- it('Should remove the video and the redundancy files', async function () {
- this.timeout(20000)
-
- await saveVideoInServers(servers, video1Server2.uuid)
- await servers[1].videos.remove({ id: video1Server2.uuid })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('With only HLS files', function () {
- const strategy = 'recently-added'
-
- before(async function () {
- this.timeout(240000)
-
- await createServers(strategy, { min_views: 3 }, false)
- })
-
- it('Should have 0 playlist redundancy on the first video', async function () {
- await check1WebSeed()
- await check0PlaylistRedundancies()
- })
-
- it('Should enable redundancy on server 1', function () {
- return enableRedundancyOnServer1()
- })
-
- it('Should still have 0 redundancy on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await wait(15000)
- await waitJobs(servers)
-
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy(strategy)
- })
-
- it('Should have 1 redundancy on the first video', async function () {
- this.timeout(160000)
-
- await servers[0].views.simulateView({ id: video1Server2.uuid })
- await servers[2].views.simulateView({ id: video1Server2.uuid })
-
- await wait(10000)
- await waitJobs(servers)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 1)
- await waitJobs(servers)
-
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy, true)
- })
-
- it('Should remove the video and the redundancy files', async function () {
- this.timeout(20000)
-
- await saveVideoInServers(servers, video1Server2.uuid)
- await servers[1].videos.remove({ id: video1Server2.uuid })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('With manual strategy', function () {
- before(function () {
- this.timeout(240000)
-
- return createServers(null)
- })
-
- it('Should have 1 webseed on the first video', async function () {
- await check1WebSeed()
- await check0PlaylistRedundancies()
- await checkStatsWithoutRedundancy('manual')
- })
-
- it('Should create a redundancy on first video', async function () {
- await servers[0].redundancy.addVideo({ videoId: video1Server2.id })
- })
-
- it('Should have 2 webseeds on the first video', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy('manual')
- })
-
- it('Should manually remove redundancies on server 1 and remove duplicated videos', async function () {
- this.timeout(80000)
-
- const body = await servers[0].redundancy.listVideos({ target: 'remote-videos' })
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
-
- const video = videos[0]
-
- for (const r of video.redundancies.files.concat(video.redundancies.streamingPlaylists)) {
- await servers[0].redundancy.removeVideo({ redundancyId: r.id })
- }
-
- await waitJobs(servers)
- await wait(5000)
-
- await check1WebSeed()
- await check0PlaylistRedundancies()
-
- await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('Test expiration', function () {
- const strategy = 'recently-added'
-
- async function checkContains (servers: PeerTubeServer[], str: string) {
- for (const server of servers) {
- const video = await server.videos.get({ id: video1Server2.uuid })
-
- for (const f of video.files) {
- expect(f.magnetUri).to.contain(str)
- }
- }
- }
-
- async function checkNotContains (servers: PeerTubeServer[], str: string) {
- for (const server of servers) {
- const video = await server.videos.get({ id: video1Server2.uuid })
-
- for (const f of video.files) {
- expect(f.magnetUri).to.not.contain(str)
- }
- }
- }
-
- before(async function () {
- this.timeout(240000)
-
- await createServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
-
- await enableRedundancyOnServer1()
- })
-
- it('Should still have 2 webseeds after 10 seconds', async function () {
- this.timeout(80000)
-
- await wait(10000)
-
- try {
- await checkContains(servers, 'http%3A%2F%2F' + servers[0].hostname + '%3A' + servers[0].port)
- } catch {
- // Maybe a server deleted a redundancy in the scheduler
- await wait(2000)
-
- await checkContains(servers, 'http%3A%2F%2F' + servers[0].hostname + '%3A' + servers[0].port)
- }
- })
-
- it('Should stop server 1 and expire video redundancy', async function () {
- this.timeout(80000)
-
- await killallServers([ servers[0] ])
-
- await wait(15000)
-
- await checkNotContains([ servers[1], servers[2] ], 'http%3A%2F%2F' + servers[0].port + '%3A' + servers[0].port)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('Test file replacement', function () {
- let video2Server2UUID: string
- const strategy = 'recently-added'
-
- before(async function () {
- this.timeout(240000)
-
- await createServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
-
- await enableRedundancyOnServer1()
-
- await waitJobs(servers)
- await servers[0].servers.waitUntilLog('Duplicated ', 5)
- await waitJobs(servers)
-
- await check2Webseeds()
- await check1PlaylistRedundancies()
- await checkStatsWith1Redundancy(strategy)
-
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 2 server 2', privacy: VideoPrivacy.PRIVATE } })
- video2Server2UUID = uuid
-
- // Wait transcoding before federation
- await waitJobs(servers)
-
- await servers[1].videos.update({ id: video2Server2UUID, attributes: { privacy: VideoPrivacy.PUBLIC } })
- })
-
- it('Should cache video 2 webseeds on the first video', async function () {
- this.timeout(240000)
-
- await waitJobs(servers)
-
- let checked = false
-
- while (checked === false) {
- await wait(1000)
-
- try {
- await check1WebSeed()
- await check0PlaylistRedundancies()
-
- await check2Webseeds(video2Server2UUID)
- await check1PlaylistRedundancies(video2Server2UUID)
-
- checked = true
- } catch {
- checked = false
- }
- }
- })
-
- it('Should disable strategy and remove redundancies', async function () {
- this.timeout(80000)
-
- await waitJobs(servers)
-
- await killallServers([ servers[0] ])
- await servers[0].run({
- redundancy: {
- videos: {
- check_interval: '1 second',
- strategies: []
- }
- }
- })
-
- await waitJobs(servers)
-
- await checkVideoFilesWereRemoved({ server: servers[0], video: video1Server2, onlyVideoFiles: true })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-})
diff --git a/server/tests/api/runners/index.ts b/server/tests/api/runners/index.ts
deleted file mode 100644
index 642a3a96d..000000000
--- a/server/tests/api/runners/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './runner-common'
-export * from './runner-live-transcoding'
-export * from './runner-socket'
-export * from './runner-studio-transcoding'
-export * from './runner-vod-transcoding'
diff --git a/server/tests/api/runners/runner-common.ts b/server/tests/api/runners/runner-common.ts
deleted file mode 100644
index 9b2eb8b27..000000000
--- a/server/tests/api/runners/runner-common.ts
+++ /dev/null
@@ -1,743 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import {
- HttpStatusCode,
- Runner,
- RunnerJob,
- RunnerJobAdmin,
- RunnerJobState,
- RunnerJobVODWebVideoTranscodingPayload,
- RunnerRegistrationToken
-} from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test runner common actions', function () {
- let server: PeerTubeServer
- let registrationToken: string
- let runnerToken: string
- let jobMaxPriority: string
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1, {
- remote_runners: {
- stalled_jobs: {
- vod: '5 seconds'
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableTranscoding({ hls: true, webVideo: true })
- await server.config.enableRemoteTranscoding()
- })
-
- describe('Managing runner registration tokens', function () {
- let base: RunnerRegistrationToken[]
- let registrationTokenToDelete: RunnerRegistrationToken
-
- it('Should have a default registration token', async function () {
- const { total, data } = await server.runnerRegistrationTokens.list()
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const token = data[0]
- expect(token.id).to.exist
- expect(token.createdAt).to.exist
- expect(token.updatedAt).to.exist
- expect(token.registeredRunnersCount).to.equal(0)
- expect(token.registrationToken).to.exist
- })
-
- it('Should create other registration tokens', async function () {
- await server.runnerRegistrationTokens.generate()
- await server.runnerRegistrationTokens.generate()
-
- const { total, data } = await server.runnerRegistrationTokens.list()
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
- })
-
- it('Should list registration tokens', async function () {
- {
- const { total, data } = await server.runnerRegistrationTokens.list({ sort: 'createdAt' })
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
- expect(new Date(data[0].createdAt)).to.be.below(new Date(data[1].createdAt))
- expect(new Date(data[1].createdAt)).to.be.below(new Date(data[2].createdAt))
-
- base = data
-
- registrationTokenToDelete = data[0]
- registrationToken = data[1].registrationToken
- }
-
- {
- const { total, data } = await server.runnerRegistrationTokens.list({ sort: '-createdAt', start: 2, count: 1 })
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(1)
- expect(data[0].registrationToken).to.equal(base[0].registrationToken)
- }
- })
-
- it('Should have appropriate registeredRunnersCount for registration tokens', async function () {
- await server.runners.register({ name: 'to delete 1', registrationToken: registrationTokenToDelete.registrationToken })
- await server.runners.register({ name: 'to delete 2', registrationToken: registrationTokenToDelete.registrationToken })
-
- const { data } = await server.runnerRegistrationTokens.list()
-
- for (const d of data) {
- if (d.registrationToken === registrationTokenToDelete.registrationToken) {
- expect(d.registeredRunnersCount).to.equal(2)
- } else {
- expect(d.registeredRunnersCount).to.equal(0)
- }
- }
-
- const { data: runners } = await server.runners.list()
- expect(runners).to.have.lengthOf(2)
- })
-
- it('Should delete a registration token', async function () {
- await server.runnerRegistrationTokens.delete({ id: registrationTokenToDelete.id })
-
- const { total, data } = await server.runnerRegistrationTokens.list({ sort: 'createdAt' })
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const d of data) {
- expect(d.registeredRunnersCount).to.equal(0)
- expect(d.registrationToken).to.not.equal(registrationTokenToDelete.registrationToken)
- }
- })
-
- it('Should have removed runners of this registration token', async function () {
- const { data: runners } = await server.runners.list()
- expect(runners).to.have.lengthOf(0)
- })
- })
-
- describe('Managing runners', function () {
- let toDelete: Runner
-
- it('Should not have runners available', async function () {
- const { total, data } = await server.runners.list()
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- })
-
- it('Should register runners', async function () {
- const now = new Date()
-
- const result = await server.runners.register({
- name: 'runner 1',
- description: 'my super runner 1',
- registrationToken
- })
- expect(result.runnerToken).to.exist
- runnerToken = result.runnerToken
-
- await server.runners.register({
- name: 'runner 2',
- registrationToken
- })
-
- const { total, data } = await server.runners.list({ sort: 'createdAt' })
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const d of data) {
- expect(d.id).to.exist
- expect(d.createdAt).to.exist
- expect(d.updatedAt).to.exist
- expect(new Date(d.createdAt)).to.be.above(now)
- expect(new Date(d.updatedAt)).to.be.above(now)
- expect(new Date(d.lastContact)).to.be.above(now)
- expect(d.ip).to.exist
- }
-
- expect(data[0].name).to.equal('runner 1')
- expect(data[0].description).to.equal('my super runner 1')
-
- expect(data[1].name).to.equal('runner 2')
- expect(data[1].description).to.be.null
-
- toDelete = data[1]
- })
-
- it('Should list runners', async function () {
- const { total, data } = await server.runners.list({ sort: '-createdAt', start: 1, count: 1 })
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('runner 1')
- })
-
- it('Should delete a runner', async function () {
- await server.runners.delete({ id: toDelete.id })
-
- const { total, data } = await server.runners.list()
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('runner 1')
- })
-
- it('Should unregister a runner', async function () {
- const registered = await server.runners.autoRegisterRunner()
-
- {
- const { total, data } = await server.runners.list()
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
- }
-
- await server.runners.unregister({ runnerToken: registered })
-
- {
- const { total, data } = await server.runners.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('runner 1')
- }
- })
- })
-
- describe('Managing runner jobs', function () {
- let jobUUID: string
- let jobToken: string
- let lastRunnerContact: Date
- let failedJob: RunnerJob
-
- async function checkMainJobState (
- mainJobState: RunnerJobState,
- otherJobStates: RunnerJobState[] = [ RunnerJobState.PENDING, RunnerJobState.WAITING_FOR_PARENT_JOB ]
- ) {
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- for (const job of data) {
- if (job.uuid === jobUUID) {
- expect(job.state.id).to.equal(mainJobState)
- } else {
- expect(otherJobStates).to.include(job.state.id)
- }
- }
- }
-
- function getMainJob () {
- return server.runnerJobs.getJob({ uuid: jobUUID })
- }
-
- describe('List jobs', function () {
-
- it('Should not have jobs', async function () {
- const { total, data } = await server.runnerJobs.list()
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- })
-
- it('Should upload a video and have available jobs', async function () {
- await server.videos.quickUpload({ name: 'to transcode' })
- await waitJobs([ server ])
-
- const { total, data } = await server.runnerJobs.list()
-
- expect(data).to.have.lengthOf(10)
- expect(total).to.equal(10)
-
- for (const job of data) {
- expect(job.startedAt).to.not.exist
- expect(job.finishedAt).to.not.exist
- expect(job.payload).to.exist
- expect(job.privatePayload).to.exist
- }
-
- const hlsJobs = data.filter(d => d.type === 'vod-hls-transcoding')
- const webVideoJobs = data.filter(d => d.type === 'vod-web-video-transcoding')
-
- expect(hlsJobs).to.have.lengthOf(5)
- expect(webVideoJobs).to.have.lengthOf(5)
-
- const pendingJobs = data.filter(d => d.state.id === RunnerJobState.PENDING)
- const waitingJobs = data.filter(d => d.state.id === RunnerJobState.WAITING_FOR_PARENT_JOB)
-
- expect(pendingJobs).to.have.lengthOf(1)
- expect(waitingJobs).to.have.lengthOf(9)
- })
-
- it('Should upload another video and list/sort jobs', async function () {
- await server.videos.quickUpload({ name: 'to transcode 2' })
- await waitJobs([ server ])
-
- {
- const { total, data } = await server.runnerJobs.list({ start: 0, count: 30 })
-
- expect(data).to.have.lengthOf(20)
- expect(total).to.equal(20)
-
- jobUUID = data[16].uuid
- }
-
- {
- const { total, data } = await server.runnerJobs.list({ start: 3, count: 1, sort: 'createdAt' })
- expect(total).to.equal(20)
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].uuid).to.equal(jobUUID)
- }
-
- {
- let previousPriority = Infinity
- const { total, data } = await server.runnerJobs.list({ start: 0, count: 100, sort: '-priority' })
- expect(total).to.equal(20)
-
- for (const job of data) {
- expect(job.priority).to.be.at.most(previousPriority)
- previousPriority = job.priority
-
- if (job.state.id === RunnerJobState.PENDING) {
- jobMaxPriority = job.uuid
- }
- }
- }
- })
-
- it('Should search jobs', async function () {
- {
- const { total, data } = await server.runnerJobs.list({ search: jobUUID })
-
- expect(data).to.have.lengthOf(1)
- expect(total).to.equal(1)
-
- expect(data[0].uuid).to.equal(jobUUID)
- }
-
- {
- const { total, data } = await server.runnerJobs.list({ search: 'toto' })
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- }
-
- {
- const { total, data } = await server.runnerJobs.list({ search: 'hls' })
-
- expect(data).to.not.have.lengthOf(0)
- expect(total).to.not.equal(0)
-
- for (const job of data) {
- expect(job.type).to.include('hls')
- }
- }
- })
-
- it('Should filter jobs', async function () {
- {
- const { total, data } = await server.runnerJobs.list({ stateOneOf: [ RunnerJobState.WAITING_FOR_PARENT_JOB ] })
-
- expect(data).to.not.have.lengthOf(0)
- expect(total).to.not.equal(0)
-
- for (const job of data) {
- expect(job.state.label).to.equal('Waiting for parent job to finish')
- }
- }
-
- {
- const { total, data } = await server.runnerJobs.list({ stateOneOf: [ RunnerJobState.COMPLETED ] })
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- }
- })
- })
-
- describe('Accept/update/abort/process a job', function () {
-
- it('Should request available jobs', async function () {
- lastRunnerContact = new Date()
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
-
- // Only optimize jobs are available
- expect(availableJobs).to.have.lengthOf(2)
-
- for (const job of availableJobs) {
- expect(job.uuid).to.exist
- expect(job.payload.input).to.exist
- expect((job.payload as RunnerJobVODWebVideoTranscodingPayload).output).to.exist
-
- expect((job as RunnerJobAdmin).privatePayload).to.not.exist
- }
-
- const hlsJobs = availableJobs.filter(d => d.type === 'vod-hls-transcoding')
- const webVideoJobs = availableJobs.filter(d => d.type === 'vod-web-video-transcoding')
-
- expect(hlsJobs).to.have.lengthOf(0)
- expect(webVideoJobs).to.have.lengthOf(2)
-
- jobUUID = webVideoJobs[0].uuid
- })
-
- it('Should have sorted available jobs by priority', async function () {
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
-
- expect(availableJobs[0].uuid).to.equal(jobMaxPriority)
- })
-
- it('Should have last runner contact updated', async function () {
- await wait(1000)
-
- const { data } = await server.runners.list({ sort: 'createdAt' })
- expect(new Date(data[0].lastContact)).to.be.above(lastRunnerContact)
- })
-
- it('Should accept a job', async function () {
- const startedAt = new Date()
-
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const checkProcessingJob = (job: RunnerJob & { jobToken?: string }, fromAccept: boolean) => {
- expect(job.uuid).to.equal(jobUUID)
-
- expect(job.type).to.equal('vod-web-video-transcoding')
- expect(job.state.label).to.equal('Processing')
- expect(job.state.id).to.equal(RunnerJobState.PROCESSING)
-
- expect(job.runner).to.exist
- expect(job.runner.name).to.equal('runner 1')
- expect(job.runner.description).to.equal('my super runner 1')
-
- expect(job.progress).to.be.null
-
- expect(job.startedAt).to.exist
- expect(new Date(job.startedAt)).to.be.above(startedAt)
-
- expect(job.finishedAt).to.not.exist
-
- expect(job.failures).to.equal(0)
-
- expect(job.payload).to.exist
-
- if (fromAccept) {
- expect(job.jobToken).to.exist
- expect((job as RunnerJobAdmin).privatePayload).to.not.exist
- } else {
- expect(job.jobToken).to.not.exist
- expect((job as RunnerJobAdmin).privatePayload).to.exist
- }
- }
-
- checkProcessingJob(job, true)
-
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- const processingJob = data.find(j => j.uuid === jobUUID)
- checkProcessingJob(processingJob, false)
-
- await checkMainJobState(RunnerJobState.PROCESSING)
- })
-
- it('Should update a job', async function () {
- await server.runnerJobs.update({ runnerToken, jobUUID, jobToken, progress: 53 })
-
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- for (const job of data) {
- if (job.state.id === RunnerJobState.PROCESSING) {
- expect(job.progress).to.equal(53)
- } else {
- expect(job.progress).to.be.null
- }
- }
- })
-
- it('Should abort a job', async function () {
- await server.runnerJobs.abort({ runnerToken, jobUUID, jobToken, reason: 'for tests' })
-
- await checkMainJobState(RunnerJobState.PENDING)
-
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
- for (const job of data) {
- expect(job.progress).to.be.null
- }
- })
-
- it('Should accept the same job again and post a success', async function () {
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- expect(availableJobs.find(j => j.uuid === jobUUID)).to.exist
-
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- await checkMainJobState(RunnerJobState.PROCESSING)
-
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- for (const job of data) {
- expect(job.progress).to.be.null
- }
-
- const payload = {
- videoFile: 'video_short.mp4'
- }
-
- await server.runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
- })
-
- it('Should not have available jobs anymore', async function () {
- await checkMainJobState(RunnerJobState.COMPLETED)
-
- const job = await getMainJob()
- expect(job.finishedAt).to.exist
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- expect(availableJobs.find(j => j.uuid === jobUUID)).to.not.exist
- })
- })
-
- describe('Error job', function () {
-
- it('Should accept another job and post an error', async function () {
- await server.runnerJobs.cancelAllJobs()
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- jobUUID = availableJobs[0].uuid
-
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- await server.runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error' })
- })
-
- it('Should have job failures increased', async function () {
- const job = await getMainJob()
- expect(job.state.id).to.equal(RunnerJobState.PENDING)
- expect(job.failures).to.equal(1)
- expect(job.error).to.be.null
- expect(job.progress).to.be.null
- expect(job.finishedAt).to.not.exist
- })
-
- it('Should error a job when job attempts is too big', async function () {
- for (let i = 0; i < 4; i++) {
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- await server.runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error ' + i })
- }
-
- const job = await getMainJob()
- expect(job.failures).to.equal(5)
- expect(job.state.id).to.equal(RunnerJobState.ERRORED)
- expect(job.state.label).to.equal('Errored')
- expect(job.error).to.equal('Error 3')
- expect(job.progress).to.be.null
- expect(job.finishedAt).to.exist
-
- failedJob = job
- })
-
- it('Should have failed children jobs too', async function () {
- const { data } = await server.runnerJobs.list({ count: 50, sort: '-updatedAt' })
-
- const children = data.filter(j => j.parent?.uuid === failedJob.uuid)
- expect(children).to.have.lengthOf(9)
-
- for (const child of children) {
- expect(child.parent.uuid).to.equal(failedJob.uuid)
- expect(child.parent.type).to.equal(failedJob.type)
- expect(child.parent.state.id).to.equal(failedJob.state.id)
- expect(child.parent.state.label).to.equal(failedJob.state.label)
-
- expect(child.state.id).to.equal(RunnerJobState.PARENT_ERRORED)
- expect(child.state.label).to.equal('Parent job failed')
- }
- })
- })
-
- describe('Cancel', function () {
-
- it('Should cancel a pending job', async function () {
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- {
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- const pendingJob = data.find(j => j.state.id === RunnerJobState.PENDING)
- jobUUID = pendingJob.uuid
-
- await server.runnerJobs.cancelByAdmin({ jobUUID })
- }
-
- {
- const job = await getMainJob()
- expect(job.state.id).to.equal(RunnerJobState.CANCELLED)
- expect(job.state.label).to.equal('Cancelled')
- }
-
- {
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
- const children = data.filter(j => j.parent?.uuid === jobUUID)
- expect(children).to.have.lengthOf(9)
-
- for (const child of children) {
- expect(child.state.id).to.equal(RunnerJobState.PARENT_CANCELLED)
- }
- }
- })
-
- it('Should cancel an already accepted job and skip success/error', async function () {
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- jobUUID = availableJobs[0].uuid
-
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- await server.runnerJobs.cancelByAdmin({ jobUUID })
-
- await server.runnerJobs.abort({ runnerToken, jobUUID, jobToken, reason: 'aborted', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Remove', function () {
-
- it('Should remove a pending job', async function () {
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- {
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- const pendingJob = data.find(j => j.state.id === RunnerJobState.PENDING)
- jobUUID = pendingJob.uuid
-
- await server.runnerJobs.deleteByAdmin({ jobUUID })
- }
-
- {
- const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
-
- const parent = data.find(j => j.uuid === jobUUID)
- expect(parent).to.not.exist
-
- const children = data.filter(j => j.parent?.uuid === jobUUID)
- expect(children).to.have.lengthOf(0)
- }
- })
- })
-
- describe('Stalled jobs', function () {
-
- it('Should abort stalled jobs', async function () {
- this.timeout(60000)
-
- await server.videos.quickUpload({ name: 'video' })
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { job: job1 } = await server.runnerJobs.autoAccept({ runnerToken })
- const { job: stalledJob } = await server.runnerJobs.autoAccept({ runnerToken })
-
- for (let i = 0; i < 6; i++) {
- await wait(2000)
-
- await server.runnerJobs.update({ runnerToken, jobToken: job1.jobToken, jobUUID: job1.uuid })
- }
-
- const refreshedJob1 = await server.runnerJobs.getJob({ uuid: job1.uuid })
- const refreshedStalledJob = await server.runnerJobs.getJob({ uuid: stalledJob.uuid })
-
- expect(refreshedJob1.state.id).to.equal(RunnerJobState.PROCESSING)
- expect(refreshedStalledJob.state.id).to.equal(RunnerJobState.PENDING)
- })
- })
-
- describe('Rate limit', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await server.kill()
-
- await server.run({
- rates_limit: {
- api: {
- max: 10
- }
- }
- })
- })
-
- it('Should rate limit an unknown runner, but not a registered one', async function () {
- this.timeout(60000)
-
- await server.videos.quickUpload({ name: 'video' })
- await waitJobs([ server ])
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken })
-
- for (let i = 0; i < 20; i++) {
- try {
- await server.runnerJobs.request({ runnerToken })
- await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
- } catch {}
- }
-
- // Invalid
- {
- await server.runnerJobs.request({ runnerToken: 'toto', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
- await server.runnerJobs.update({
- runnerToken: 'toto',
- jobToken: job.jobToken,
- jobUUID: job.uuid,
- expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
- })
- }
-
- // Not provided
- {
- await server.runnerJobs.request({ runnerToken: undefined, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
- await server.runnerJobs.update({
- runnerToken: undefined,
- jobToken: job.jobToken,
- jobUUID: job.uuid,
- expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
- })
- }
-
- // Registered
- {
- await server.runnerJobs.request({ runnerToken })
- await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
- }
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/runners/runner-live-transcoding.ts b/server/tests/api/runners/runner-live-transcoding.ts
deleted file mode 100644
index b11d54039..000000000
--- a/server/tests/api/runners/runner-live-transcoding.ts
+++ /dev/null
@@ -1,330 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { readFile } from 'fs-extra'
-import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
-import {
- HttpStatusCode,
- LiveRTMPHLSTranscodingUpdatePayload,
- LiveVideo,
- LiveVideoError,
- RunnerJob,
- RunnerJobLiveRTMPHLSTranscodingPayload,
- Video,
- VideoPrivacy,
- VideoState
-} from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- makeRawRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- testFfmpegStreamError,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test runner live transcoding', function () {
- let server: PeerTubeServer
- let runnerToken: string
- let baseUrl: string
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableRemoteTranscoding()
- await server.config.enableTranscoding()
- runnerToken = await server.runners.autoRegisterRunner()
-
- baseUrl = server.url + '/static/streaming-playlists/hls'
- })
-
- describe('Without transcoding enabled', function () {
-
- before(async function () {
- await server.config.enableLive({
- allowReplay: false,
- resolutions: 'min',
- transcoding: false
- })
- })
-
- it('Should not have available jobs', async function () {
- this.timeout(120000)
-
- const { live, video } = await server.live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await server.live.waitUntilPublished({ videoId: video.id })
-
- await waitJobs([ server ])
-
- const { availableJobs } = await server.runnerJobs.requestLive({ runnerToken })
- expect(availableJobs).to.have.lengthOf(0)
-
- await stopFfmpeg(ffmpegCommand)
- })
- })
-
- describe('With transcoding enabled on classic live', function () {
- let live: LiveVideo
- let video: Video
- let ffmpegCommand: FfmpegCommand
- let jobUUID: string
- let acceptedJob: RunnerJob & { jobToken: string }
-
- async function testPlaylistFile (fixture: string, expected: string) {
- const text = await server.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/${fixture}` })
- expect(await readFile(buildAbsoluteFixturePath(expected), 'utf-8')).to.equal(text)
-
- }
-
- async function testTSFile (fixture: string, expected: string) {
- const { body } = await makeRawRequest({ url: `${baseUrl}/${video.uuid}/${fixture}`, expectedStatus: HttpStatusCode.OK_200 })
- expect(await readFile(buildAbsoluteFixturePath(expected))).to.deep.equal(body)
- }
-
- before(async function () {
- await server.config.enableLive({
- allowReplay: true,
- resolutions: 'max',
- transcoding: true
- })
- })
-
- it('Should publish a a live and have available jobs', async function () {
- this.timeout(120000)
-
- const data = await server.live.quickCreate({ permanentLive: false, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
- live = data.live
- video = data.video
-
- ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await waitJobs([ server ])
-
- const job = await server.runnerJobs.requestLiveJob(runnerToken)
- jobUUID = job.uuid
-
- expect(job.type).to.equal('live-rtmp-hls-transcoding')
- expect(job.payload.input.rtmpUrl).to.exist
-
- expect(job.payload.output.toTranscode).to.have.lengthOf(5)
-
- for (const { resolution, fps } of job.payload.output.toTranscode) {
- expect([ 720, 480, 360, 240, 144 ]).to.contain(resolution)
-
- expect(fps).to.be.above(25)
- expect(fps).to.be.below(70)
- }
- })
-
- it('Should update the live with a new chunk', async function () {
- this.timeout(120000)
-
- const { job } = await server.runnerJobs.accept({ jobUUID, runnerToken })
- acceptedJob = job
-
- {
- const payload: LiveRTMPHLSTranscodingUpdatePayload = {
- masterPlaylistFile: 'live/master.m3u8',
- resolutionPlaylistFile: 'live/0.m3u8',
- resolutionPlaylistFilename: '0.m3u8',
- type: 'add-chunk',
- videoChunkFile: 'live/0-000067.ts',
- videoChunkFilename: '0-000067.ts'
- }
- await server.runnerJobs.update({ jobUUID, runnerToken, jobToken: job.jobToken, payload, progress: 50 })
-
- const updatedJob = await server.runnerJobs.getJob({ uuid: job.uuid })
- expect(updatedJob.progress).to.equal(50)
- }
-
- {
- const payload: LiveRTMPHLSTranscodingUpdatePayload = {
- resolutionPlaylistFile: 'live/1.m3u8',
- resolutionPlaylistFilename: '1.m3u8',
- type: 'add-chunk',
- videoChunkFile: 'live/1-000068.ts',
- videoChunkFilename: '1-000068.ts'
- }
- await server.runnerJobs.update({ jobUUID, runnerToken, jobToken: job.jobToken, payload })
- }
-
- await wait(1000)
-
- await testPlaylistFile('master.m3u8', 'live/master.m3u8')
- await testPlaylistFile('0.m3u8', 'live/0.m3u8')
- await testPlaylistFile('1.m3u8', 'live/1.m3u8')
-
- await testTSFile('0-000067.ts', 'live/0-000067.ts')
- await testTSFile('1-000068.ts', 'live/1-000068.ts')
- })
-
- it('Should replace existing m3u8 on update', async function () {
- this.timeout(120000)
-
- const payload: LiveRTMPHLSTranscodingUpdatePayload = {
- masterPlaylistFile: 'live/1.m3u8',
- resolutionPlaylistFilename: '0.m3u8',
- resolutionPlaylistFile: 'live/1.m3u8',
- type: 'add-chunk',
- videoChunkFile: 'live/1-000069.ts',
- videoChunkFilename: '1-000068.ts'
- }
- await server.runnerJobs.update({ jobUUID, runnerToken, jobToken: acceptedJob.jobToken, payload })
- await wait(1000)
-
- await testPlaylistFile('master.m3u8', 'live/1.m3u8')
- await testPlaylistFile('0.m3u8', 'live/1.m3u8')
- await testTSFile('1-000068.ts', 'live/1-000069.ts')
- })
-
- it('Should update the live with removed chunks', async function () {
- this.timeout(120000)
-
- const payload: LiveRTMPHLSTranscodingUpdatePayload = {
- resolutionPlaylistFile: 'live/0.m3u8',
- resolutionPlaylistFilename: '0.m3u8',
- type: 'remove-chunk',
- videoChunkFilename: '1-000068.ts'
- }
- await server.runnerJobs.update({ jobUUID, runnerToken, jobToken: acceptedJob.jobToken, payload })
-
- await wait(1000)
-
- await server.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/master.m3u8` })
- await server.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/0.m3u8` })
- await server.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/1.m3u8` })
- await makeRawRequest({ url: `${baseUrl}/${video.uuid}/0-000067.ts`, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: `${baseUrl}/${video.uuid}/1-000068.ts`, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should complete the live and save the replay', async function () {
- this.timeout(120000)
-
- for (const segment of [ '0-000069.ts', '0-000070.ts' ]) {
- const payload: LiveRTMPHLSTranscodingUpdatePayload = {
- masterPlaylistFile: 'live/master.m3u8',
- resolutionPlaylistFilename: '0.m3u8',
- resolutionPlaylistFile: 'live/0.m3u8',
- type: 'add-chunk',
- videoChunkFile: 'live/' + segment,
- videoChunkFilename: segment
- }
- await server.runnerJobs.update({ jobUUID, runnerToken, jobToken: acceptedJob.jobToken, payload })
-
- await wait(1000)
- }
-
- await waitJobs([ server ])
-
- {
- const { state } = await server.videos.get({ id: video.uuid })
- expect(state.id).to.equal(VideoState.PUBLISHED)
- }
-
- await stopFfmpeg(ffmpegCommand)
-
- await server.runnerJobs.success({ jobUUID, runnerToken, jobToken: acceptedJob.jobToken, payload: {} })
-
- await wait(1500)
- await waitJobs([ server ])
-
- {
- const { state } = await server.videos.get({ id: video.uuid })
- expect(state.id).to.equal(VideoState.LIVE_ENDED)
-
- const session = await server.live.findLatestSession({ videoId: video.uuid })
- expect(session.error).to.be.null
- }
- })
- })
-
- describe('With transcoding enabled on cancelled/aborted/errored live', function () {
- let live: LiveVideo
- let video: Video
- let ffmpegCommand: FfmpegCommand
-
- async function prepare () {
- ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await server.runnerJobs.requestLiveJob(runnerToken)
-
- const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'live-rtmp-hls-transcoding' })
-
- return job
- }
-
- async function checkSessionError (error: LiveVideoError) {
- await wait(1500)
- await waitJobs([ server ])
-
- const session = await server.live.findLatestSession({ videoId: video.uuid })
- expect(session.error).to.equal(error)
- }
-
- before(async function () {
- await server.config.enableLive({
- allowReplay: true,
- resolutions: 'max',
- transcoding: true
- })
-
- const data = await server.live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
- live = data.live
- video = data.video
- })
-
- it('Should abort a running live', async function () {
- this.timeout(120000)
-
- const job = await prepare()
-
- await Promise.all([
- server.runnerJobs.abort({ jobUUID: job.uuid, runnerToken, jobToken: job.jobToken, reason: 'abort' }),
- testFfmpegStreamError(ffmpegCommand, true)
- ])
-
- // Abort is not supported
- await checkSessionError(LiveVideoError.RUNNER_JOB_ERROR)
- })
-
- it('Should cancel a running live', async function () {
- this.timeout(120000)
-
- const job = await prepare()
-
- await Promise.all([
- server.runnerJobs.cancelByAdmin({ jobUUID: job.uuid }),
- testFfmpegStreamError(ffmpegCommand, true)
- ])
-
- await checkSessionError(LiveVideoError.RUNNER_JOB_CANCEL)
- })
-
- it('Should error a running live', async function () {
- this.timeout(120000)
-
- const job = await prepare()
-
- await Promise.all([
- server.runnerJobs.error({ jobUUID: job.uuid, runnerToken, jobToken: job.jobToken, message: 'error' }),
- testFfmpegStreamError(ffmpegCommand, true)
- ])
-
- await checkSessionError(LiveVideoError.RUNNER_JOB_ERROR)
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/runners/runner-socket.ts b/server/tests/api/runners/runner-socket.ts
deleted file mode 100644
index 215164e48..000000000
--- a/server/tests/api/runners/runner-socket.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test runner socket', function () {
- let server: PeerTubeServer
- let runnerToken: string
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableTranscoding({ hls: true, webVideo: true })
- await server.config.enableRemoteTranscoding()
- runnerToken = await server.runners.autoRegisterRunner()
- })
-
- it('Should throw an error without runner token', function (done) {
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken: null })
- localSocket.on('connect_error', err => {
- expect(err.message).to.contain('No runner token provided')
- done()
- })
- })
-
- it('Should throw an error with a bad runner token', function (done) {
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken: 'ergag' })
- localSocket.on('connect_error', err => {
- expect(err.message).to.contain('Invalid runner token')
- done()
- })
- })
-
- it('Should not send ping if there is no available jobs', async function () {
- let pings = 0
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken })
- localSocket.on('available-jobs', () => pings++)
-
- expect(pings).to.equal(0)
- })
-
- it('Should send a ping on available job', async function () {
- let pings = 0
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken })
- localSocket.on('available-jobs', () => pings++)
-
- await server.videos.quickUpload({ name: 'video1' })
- await waitJobs([ server ])
-
- // eslint-disable-next-line no-unmodified-loop-condition
- while (pings !== 1) {
- await wait(500)
- }
-
- await server.videos.quickUpload({ name: 'video2' })
- await waitJobs([ server ])
-
- // eslint-disable-next-line no-unmodified-loop-condition
- while ((pings as number) !== 2) {
- await wait(500)
- }
-
- await server.runnerJobs.cancelAllJobs()
- })
-
- it('Should send a ping when a child is ready', async function () {
- let pings = 0
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken })
- localSocket.on('available-jobs', () => pings++)
-
- await server.videos.quickUpload({ name: 'video3' })
- await waitJobs([ server ])
-
- // eslint-disable-next-line no-unmodified-loop-condition
- while (pings !== 1) {
- await wait(500)
- }
-
- await server.runnerJobs.autoProcessWebVideoJob(runnerToken)
- await waitJobs([ server ])
-
- // eslint-disable-next-line no-unmodified-loop-condition
- while ((pings as number) !== 2) {
- await wait(500)
- }
- })
-
- it('Should not send a ping if the ended job does not have a child', async function () {
- let pings = 0
- const localSocket = server.socketIO.getRunnersSocket({ runnerToken })
- localSocket.on('available-jobs', () => pings++)
-
- const { availableJobs } = await server.runnerJobs.request({ runnerToken })
- const job = availableJobs.find(j => j.type === 'vod-web-video-transcoding')
- await server.runnerJobs.autoProcessWebVideoJob(runnerToken, job.uuid)
-
- // Wait for debounce
- await wait(1000)
- await waitJobs([ server ])
-
- expect(pings).to.equal(0)
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/runners/runner-studio-transcoding.ts b/server/tests/api/runners/runner-studio-transcoding.ts
deleted file mode 100644
index f5cea6cea..000000000
--- a/server/tests/api/runners/runner-studio-transcoding.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readFile } from 'fs-extra'
-import { checkPersistentTmpIsEmpty, checkVideoDuration } from '@server/tests/shared'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import {
- RunnerJobStudioTranscodingPayload,
- VideoStudioTranscodingSuccess,
- VideoState,
- VideoStudioTask,
- VideoStudioTaskIntro
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- VideoStudioCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test runner video studio transcoding', function () {
- let servers: PeerTubeServer[] = []
- let runnerToken: string
- let videoUUID: string
- let jobUUID: string
-
- async function renewStudio (tasks: VideoStudioTask[] = VideoStudioCommand.getComplexTask()) {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- videoUUID = uuid
-
- await waitJobs(servers)
-
- await servers[0].videoStudio.createEditionTasks({ videoId: uuid, tasks })
- await waitJobs(servers)
-
- const { availableJobs } = await servers[0].runnerJobs.request({ runnerToken })
- expect(availableJobs).to.have.lengthOf(1)
-
- jobUUID = availableJobs[0].uuid
- }
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
- await servers[0].config.enableStudio()
- await servers[0].config.enableRemoteStudio()
-
- runnerToken = await servers[0].runners.autoRegisterRunner()
- })
-
- it('Should error a studio transcoding job', async function () {
- this.timeout(60000)
-
- await renewStudio()
-
- for (let i = 0; i < 5; i++) {
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- const jobToken = job.jobToken
-
- await servers[0].runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error' })
- }
-
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
-
- await checkPersistentTmpIsEmpty(servers[0])
- })
-
- it('Should cancel a transcoding job', async function () {
- this.timeout(60000)
-
- await renewStudio()
-
- await servers[0].runnerJobs.cancelByAdmin({ jobUUID })
-
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
-
- await checkPersistentTmpIsEmpty(servers[0])
- })
-
- it('Should execute a remote studio job', async function () {
- this.timeout(240_000)
-
- const tasks = [
- {
- name: 'add-outro' as 'add-outro',
- options: {
- file: 'video_short.webm'
- }
- },
- {
- name: 'add-watermark' as 'add-watermark',
- options: {
- file: 'custom-thumbnail.png'
- }
- },
- {
- name: 'add-intro' as 'add-intro',
- options: {
- file: 'video_very_short_240p.mp4'
- }
- }
- ]
-
- await renewStudio(tasks)
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 5)
- }
-
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- const jobToken = job.jobToken
-
- expect(job.type === 'video-studio-transcoding')
- expect(job.payload.input.videoFileUrl).to.exist
-
- // Check video input file
- {
- await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- }
-
- // Check task files
- for (let i = 0; i < tasks.length; i++) {
- const task = tasks[i]
- const payloadTask = job.payload.tasks[i]
-
- expect(payloadTask.name).to.equal(task.name)
-
- const inputFile = await readFile(buildAbsoluteFixturePath(task.options.file))
-
- const { body } = await servers[0].runnerJobs.getJobFile({
- url: (payloadTask as VideoStudioTaskIntro).options.file as string,
- jobToken,
- runnerToken
- })
-
- expect(body).to.deep.equal(inputFile)
- }
-
- const payload: VideoStudioTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 2)
- }
-
- await checkPersistentTmpIsEmpty(servers[0])
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/runners/runner-vod-transcoding.ts b/server/tests/api/runners/runner-vod-transcoding.ts
deleted file mode 100644
index ee6be4ee9..000000000
--- a/server/tests/api/runners/runner-vod-transcoding.ts
+++ /dev/null
@@ -1,545 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readFile } from 'fs-extra'
-import { completeCheckHlsPlaylist } from '@server/tests/shared'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import {
- HttpStatusCode,
- RunnerJobSuccessPayload,
- RunnerJobVODAudioMergeTranscodingPayload,
- RunnerJobVODHLSTranscodingPayload,
- RunnerJobVODPayload,
- RunnerJobVODWebVideoTranscodingPayload,
- VideoState,
- VODAudioMergeTranscodingSuccess,
- VODHLSTranscodingSuccess,
- VODWebVideoTranscodingSuccess
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- makeRawRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-async function processAllJobs (server: PeerTubeServer, runnerToken: string) {
- do {
- const { availableJobs } = await server.runnerJobs.requestVOD({ runnerToken })
- if (availableJobs.length === 0) break
-
- const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID: availableJobs[0].uuid })
-
- const payload: RunnerJobSuccessPayload = {
- videoFile: `video_short_${job.payload.output.resolution}p.mp4`,
- resolutionPlaylistFile: `video_short_${job.payload.output.resolution}p.m3u8`
- }
- await server.runnerJobs.success({ runnerToken, jobUUID: job.uuid, jobToken: job.jobToken, payload })
- } while (true)
-
- await waitJobs([ server ])
-}
-
-describe('Test runner VOD transcoding', function () {
- let servers: PeerTubeServer[] = []
- let runnerToken: string
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableRemoteTranscoding()
- runnerToken = await servers[0].runners.autoRegisterRunner()
- })
-
- describe('Without transcoding', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.disableTranscoding()
- await servers[0].videos.quickUpload({ name: 'video' })
-
- await waitJobs(servers)
- })
-
- it('Should not have available jobs', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(0)
- })
- })
-
- describe('With classic transcoding enabled', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
- })
-
- it('Should error a transcoding job', async function () {
- this.timeout(60000)
-
- await servers[0].runnerJobs.cancelAllJobs()
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- await waitJobs(servers)
-
- const { availableJobs } = await servers[0].runnerJobs.request({ runnerToken })
- const jobUUID = availableJobs[0].uuid
-
- for (let i = 0; i < 5; i++) {
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- const jobToken = job.jobToken
-
- await servers[0].runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error' })
- }
-
- const video = await servers[0].videos.get({ id: uuid })
- expect(video.state.id).to.equal(VideoState.TRANSCODING_FAILED)
- })
-
- it('Should cancel a transcoding job', async function () {
- await servers[0].runnerJobs.cancelAllJobs()
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- await waitJobs(servers)
-
- const { availableJobs } = await servers[0].runnerJobs.request({ runnerToken })
- const jobUUID = availableJobs[0].uuid
-
- await servers[0].runnerJobs.cancelByAdmin({ jobUUID })
-
- const video = await servers[0].videos.get({ id: uuid })
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
- })
- })
-
- describe('Web video transcoding only', function () {
- let videoUUID: string
- let jobToken: string
- let jobUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].runnerJobs.cancelAllJobs()
- await servers[0].config.enableTranscoding({ hls: false, webVideo: true })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'web video', fixture: 'video_short.webm' })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should have jobs available for remote runners', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(1)
-
- jobUUID = availableJobs[0].uuid
- })
-
- it('Should have a valid first transcoding job', async function () {
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- expect(job.type === 'vod-web-video-transcoding')
- expect(job.payload.input.videoFileUrl).to.exist
- expect(job.payload.output.resolution).to.equal(720)
- expect(job.payload.output.fps).to.equal(25)
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('video_short.webm'))
-
- expect(body).to.deep.equal(inputFile)
- })
-
- it('Should transcode the max video resolution and send it back to the server', async function () {
- this.timeout(60000)
-
- const payload: VODWebVideoTranscodingSuccess = {
- videoFile: 'video_short.mp4'
- }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
-
- const { body } = await makeRawRequest({ url: video.files[0].fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(body).to.deep.equal(await readFile(buildAbsoluteFixturePath('video_short.mp4')))
- }
- })
-
- it('Should have 4 lower resolution to transcode', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(4)
-
- for (const resolution of [ 480, 360, 240, 144 ]) {
- const job = availableJobs.find(j => j.payload.output.resolution === resolution)
- expect(job).to.exist
- expect(job.type).to.equal('vod-web-video-transcoding')
-
- if (resolution === 240) jobUUID = job.uuid
- }
- })
-
- it('Should process one of these transcoding jobs', async function () {
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('video_short.mp4'))
-
- expect(body).to.deep.equal(inputFile)
-
- const payload: VODWebVideoTranscodingSuccess = { videoFile: `video_short_${job.payload.output.resolution}p.mp4` }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
- })
-
- it('Should process all other jobs', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(3)
-
- for (const resolution of [ 480, 360, 144 ]) {
- const availableJob = availableJobs.find(j => j.payload.output.resolution === resolution)
- expect(availableJob).to.exist
- jobUUID = availableJob.uuid
-
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('video_short.mp4'))
- expect(body).to.deep.equal(inputFile)
-
- const payload: VODWebVideoTranscodingSuccess = { videoFile: `video_short_${resolution}p.mp4` }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
- }
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.files).to.have.lengthOf(5)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
-
- const { body } = await makeRawRequest({ url: video.files[0].fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(body).to.deep.equal(await readFile(buildAbsoluteFixturePath('video_short.mp4')))
-
- for (const file of video.files) {
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
-
- it('Should not have available jobs anymore', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(0)
- })
- })
-
- describe('HLS transcoding only', function () {
- let videoUUID: string
- let jobToken: string
- let jobUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: false })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'hls video', fixture: 'video_short.webm' })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should run the optimize job', async function () {
- this.timeout(60000)
-
- await servers[0].runnerJobs.autoProcessWebVideoJob(runnerToken)
- })
-
- it('Should have 5 HLS resolution to transcode', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(5)
-
- for (const resolution of [ 720, 480, 360, 240, 144 ]) {
- const job = availableJobs.find(j => j.payload.output.resolution === resolution)
- expect(job).to.exist
- expect(job.type).to.equal('vod-hls-transcoding')
-
- if (resolution === 480) jobUUID = job.uuid
- }
- })
-
- it('Should process one of these transcoding jobs', async function () {
- this.timeout(60000)
-
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('video_short.mp4'))
-
- expect(body).to.deep.equal(inputFile)
-
- const payload: VODHLSTranscodingSuccess = {
- videoFile: 'video_short_480p.mp4',
- resolutionPlaylistFile: 'video_short_480p.m3u8'
- }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const hls = video.streamingPlaylists[0]
- expect(hls.files).to.have.lengthOf(1)
-
- await completeCheckHlsPlaylist({ videoUUID, hlsOnly: false, servers, resolutions: [ 480 ] })
- }
- })
-
- it('Should process all other jobs', async function () {
- this.timeout(60000)
-
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(4)
-
- let maxQualityFile = 'video_short.mp4'
-
- for (const resolution of [ 720, 360, 240, 144 ]) {
- const availableJob = availableJobs.find(j => j.payload.output.resolution === resolution)
- expect(availableJob).to.exist
- jobUUID = availableJob.uuid
-
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath(maxQualityFile))
- expect(body).to.deep.equal(inputFile)
-
- const payload: VODHLSTranscodingSuccess = {
- videoFile: `video_short_${resolution}p.mp4`,
- resolutionPlaylistFile: `video_short_${resolution}p.m3u8`
- }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- if (resolution === 720) {
- maxQualityFile = 'video_short_720p.mp4'
- }
- }
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.files).to.have.lengthOf(0)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const hls = video.streamingPlaylists[0]
- expect(hls.files).to.have.lengthOf(5)
-
- await completeCheckHlsPlaylist({ videoUUID, hlsOnly: true, servers, resolutions: [ 720, 480, 360, 240, 144 ] })
- }
- })
-
- it('Should not have available jobs anymore', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(0)
- })
- })
-
- describe('Web video and HLS transcoding', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
-
- await servers[0].videos.quickUpload({ name: 'web video and hls video', fixture: 'video_short.webm' })
-
- await waitJobs(servers)
- })
-
- it('Should process the first optimize job', async function () {
- this.timeout(60000)
-
- await servers[0].runnerJobs.autoProcessWebVideoJob(runnerToken)
- })
-
- it('Should have 9 jobs to process', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
-
- expect(availableJobs).to.have.lengthOf(9)
-
- const webVideoJobs = availableJobs.filter(j => j.type === 'vod-web-video-transcoding')
- const hlsJobs = availableJobs.filter(j => j.type === 'vod-hls-transcoding')
-
- expect(webVideoJobs).to.have.lengthOf(4)
- expect(hlsJobs).to.have.lengthOf(5)
- })
-
- it('Should process all available jobs', async function () {
- await processAllJobs(servers[0], runnerToken)
- })
- })
-
- describe('Audio merge transcoding', function () {
- let videoUUID: string
- let jobToken: string
- let jobUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
-
- const attributes = { name: 'audio_with_preview', previewfile: 'custom-preview.jpg', fixture: 'sample.ogg' }
- const { uuid } = await servers[0].videos.upload({ attributes, mode: 'legacy' })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should have an audio merge transcoding job', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(1)
-
- expect(availableJobs[0].type).to.equal('vod-audio-merge-transcoding')
-
- jobUUID = availableJobs[0].uuid
- })
-
- it('Should have a valid remote audio merge transcoding job', async function () {
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- expect(job.type === 'vod-audio-merge-transcoding')
- expect(job.payload.input.audioFileUrl).to.exist
- expect(job.payload.input.previewFileUrl).to.exist
- expect(job.payload.output.resolution).to.equal(480)
-
- {
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.audioFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('sample.ogg'))
- expect(body).to.deep.equal(inputFile)
- }
-
- {
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.previewFileUrl, jobToken, runnerToken })
-
- const video = await servers[0].videos.get({ id: videoUUID })
- const { body: inputFile } = await makeGetRequest({
- url: servers[0].url,
- path: video.previewPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(body).to.deep.equal(inputFile)
- }
- })
-
- it('Should merge the audio', async function () {
- this.timeout(60000)
-
- const payload: VODAudioMergeTranscodingSuccess = { videoFile: 'video_short_480p.mp4' }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
-
- const { body } = await makeRawRequest({ url: video.files[0].fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(body).to.deep.equal(await readFile(buildAbsoluteFixturePath('video_short_480p.mp4')))
- }
- })
-
- it('Should have 7 lower resolutions to transcode', async function () {
- const { availableJobs } = await servers[0].runnerJobs.requestVOD({ runnerToken })
- expect(availableJobs).to.have.lengthOf(7)
-
- for (const resolution of [ 360, 240, 144 ]) {
- const jobs = availableJobs.filter(j => j.payload.output.resolution === resolution)
- expect(jobs).to.have.lengthOf(2)
- }
-
- jobUUID = availableJobs.find(j => j.payload.output.resolution === 480).uuid
- })
-
- it('Should process one other job', async function () {
- this.timeout(60000)
-
- const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
- jobToken = job.jobToken
-
- const { body } = await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
- const inputFile = await readFile(buildAbsoluteFixturePath('video_short_480p.mp4'))
- expect(body).to.deep.equal(inputFile)
-
- const payload: VODHLSTranscodingSuccess = {
- videoFile: `video_short_480p.mp4`,
- resolutionPlaylistFile: `video_short_480p.m3u8`
- }
- await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
-
- await waitJobs(servers)
- })
-
- it('Should have the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const hls = video.streamingPlaylists[0]
- expect(hls.files).to.have.lengthOf(1)
-
- await completeCheckHlsPlaylist({ videoUUID, hlsOnly: false, servers, resolutions: [ 480 ] })
- }
- })
-
- it('Should process all available jobs', async function () {
- await processAllJobs(servers[0], runnerToken)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/search/index.ts b/server/tests/api/search/index.ts
deleted file mode 100644
index a976d210d..000000000
--- a/server/tests/api/search/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import './search-activitypub-video-playlists'
-import './search-activitypub-video-channels'
-import './search-activitypub-videos'
-import './search-channels'
-import './search-index'
-import './search-playlists'
-import './search-videos'
diff --git a/server/tests/api/search/search-activitypub-video-channels.ts b/server/tests/api/search/search-activitypub-video-channels.ts
deleted file mode 100644
index 003bd34d0..000000000
--- a/server/tests/api/search/search-activitypub-video-channels.ts
+++ /dev/null
@@ -1,255 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideoChannel } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test ActivityPub video channels search', function () {
- let servers: PeerTubeServer[]
- let userServer2Token: string
- let videoServer2UUID: string
- let channelIdServer2: number
- let command: SearchCommand
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- {
- await servers[0].users.create({ username: 'user1_server1', password: 'password' })
- const channel = {
- name: 'channel1_server1',
- displayName: 'Channel 1 server 1'
- }
- await servers[0].channels.create({ attributes: channel })
- }
-
- {
- const user = { username: 'user1_server2', password: 'password' }
- await servers[1].users.create({ username: user.username, password: user.password })
- userServer2Token = await servers[1].login.getAccessToken(user)
-
- const channel = {
- name: 'channel1_server2',
- displayName: 'Channel 1 server 2'
- }
- const created = await servers[1].channels.create({ token: userServer2Token, attributes: channel })
- channelIdServer2 = created.id
-
- const attributes = { name: 'video 1 server 2', channelId: channelIdServer2 }
- const { uuid } = await servers[1].videos.upload({ token: userServer2Token, attributes })
- videoServer2UUID = uuid
- }
-
- await waitJobs(servers)
-
- command = servers[0].search
- })
-
- it('Should not find a remote video channel', async function () {
- this.timeout(15000)
-
- {
- const search = servers[1].url + '/video-channels/channel1_server3'
- const body = await command.searchChannels({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- // Without token
- const search = servers[1].url + '/video-channels/channel1_server2'
- const body = await command.searchChannels({ search })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should search a local video channel', async function () {
- const searches = [
- servers[0].url + '/video-channels/channel1_server1',
- 'channel1_server1@' + servers[0].host
- ]
-
- for (const search of searches) {
- const body = await command.searchChannels({ search })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('channel1_server1')
- expect(body.data[0].displayName).to.equal('Channel 1 server 1')
- }
- })
-
- it('Should search a local video channel with an alternative URL', async function () {
- const search = servers[0].url + '/c/channel1_server1'
-
- for (const token of [ undefined, servers[0].accessToken ]) {
- const body = await command.searchChannels({ search, token })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('channel1_server1')
- expect(body.data[0].displayName).to.equal('Channel 1 server 1')
- }
- })
-
- it('Should search a local video channel with a query in URL', async function () {
- const searches = [
- servers[0].url + '/video-channels/channel1_server1',
- servers[0].url + '/c/channel1_server1'
- ]
-
- for (const search of searches) {
- for (const token of [ undefined, servers[0].accessToken ]) {
- const body = await command.searchChannels({ search: search + '?param=2', token })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('channel1_server1')
- expect(body.data[0].displayName).to.equal('Channel 1 server 1')
- }
- }
- })
-
- it('Should search a remote video channel with URL or handle', async function () {
- const searches = [
- servers[1].url + '/video-channels/channel1_server2',
- servers[1].url + '/c/channel1_server2',
- servers[1].url + '/c/channel1_server2/videos',
- 'channel1_server2@' + servers[1].host
- ]
-
- for (const search of searches) {
- const body = await command.searchChannels({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('channel1_server2')
- expect(body.data[0].displayName).to.equal('Channel 1 server 2')
- }
- })
-
- it('Should not list this remote video channel', async function () {
- const body = await servers[0].channels.list()
- expect(body.total).to.equal(3)
- expect(body.data).to.have.lengthOf(3)
- expect(body.data[0].name).to.equal('channel1_server1')
- expect(body.data[1].name).to.equal('user1_server1_channel')
- expect(body.data[2].name).to.equal('root_channel')
- })
-
- it('Should list video channel videos of server 2 without token', async function () {
- this.timeout(30000)
-
- await waitJobs(servers)
-
- const { total, data } = await servers[0].videos.listByChannel({
- token: null,
- handle: 'channel1_server2@' + servers[1].host
- })
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- })
-
- it('Should list video channel videos of server 2 with token', async function () {
- const { total, data } = await servers[0].videos.listByChannel({
- handle: 'channel1_server2@' + servers[1].host
- })
-
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('video 1 server 2')
- })
-
- it('Should update video channel of server 2, and refresh it on server 1', async function () {
- this.timeout(120000)
-
- await servers[1].channels.update({
- token: userServer2Token,
- channelName: 'channel1_server2',
- attributes: { displayName: 'channel updated' }
- })
- await servers[1].users.updateMe({ token: userServer2Token, displayName: 'user updated' })
-
- await waitJobs(servers)
- // Expire video channel
- await wait(10000)
-
- const search = servers[1].url + '/video-channels/channel1_server2'
- const body = await command.searchChannels({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const videoChannel: VideoChannel = body.data[0]
- expect(videoChannel.displayName).to.equal('channel updated')
-
- // We don't return the owner account for now
- // expect(videoChannel.ownerAccount.displayName).to.equal('user updated')
- })
-
- it('Should update and add a video on server 2, and update it on server 1 after a search', async function () {
- this.timeout(120000)
-
- await servers[1].videos.update({ token: userServer2Token, id: videoServer2UUID, attributes: { name: 'video 1 updated' } })
- await servers[1].videos.upload({ token: userServer2Token, attributes: { name: 'video 2 server 2', channelId: channelIdServer2 } })
-
- await waitJobs(servers)
-
- // Expire video channel
- await wait(10000)
-
- const search = servers[1].url + '/video-channels/channel1_server2'
- await command.searchChannels({ search, token: servers[0].accessToken })
-
- await waitJobs(servers)
-
- const handle = 'channel1_server2@' + servers[1].host
- const { total, data } = await servers[0].videos.listByChannel({ handle, sort: '-createdAt' })
-
- expect(total).to.equal(2)
- expect(data[0].name).to.equal('video 2 server 2')
- expect(data[1].name).to.equal('video 1 updated')
- })
-
- it('Should delete video channel of server 2, and delete it on server 1', async function () {
- this.timeout(120000)
-
- await servers[1].channels.delete({ token: userServer2Token, channelName: 'channel1_server2' })
-
- await waitJobs(servers)
- // Expire video
- await wait(10000)
-
- const search = servers[1].url + '/video-channels/channel1_server2'
- const body = await command.searchChannels({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/search/search-activitypub-video-playlists.ts b/server/tests/api/search/search-activitypub-video-playlists.ts
deleted file mode 100644
index 2bb5d869a..000000000
--- a/server/tests/api/search/search-activitypub-video-playlists.ts
+++ /dev/null
@@ -1,214 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideoPlaylistPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test ActivityPub playlists search', function () {
- let servers: PeerTubeServer[]
- let playlistServer1UUID: string
- let playlistServer2UUID: string
- let video2Server2: string
-
- let command: SearchCommand
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- {
- const video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid
- const video2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).uuid
-
- const attributes = {
- displayName: 'playlist 1 on server 1',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].store.channel.id
- }
- const created = await servers[0].playlists.create({ attributes })
- playlistServer1UUID = created.uuid
-
- for (const videoId of [ video1, video2 ]) {
- await servers[0].playlists.addElement({ playlistId: playlistServer1UUID, attributes: { videoId } })
- }
- }
-
- {
- const videoId = (await servers[1].videos.quickUpload({ name: 'video 1' })).uuid
- video2Server2 = (await servers[1].videos.quickUpload({ name: 'video 2' })).uuid
-
- const attributes = {
- displayName: 'playlist 1 on server 2',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].store.channel.id
- }
- const created = await servers[1].playlists.create({ attributes })
- playlistServer2UUID = created.uuid
-
- await servers[1].playlists.addElement({ playlistId: playlistServer2UUID, attributes: { videoId } })
- }
-
- await waitJobs(servers)
-
- command = servers[0].search
- })
-
- it('Should not find a remote playlist', async function () {
- {
- const search = servers[1].url + '/video-playlists/43'
- const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- // Without token
- const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
- const body = await command.searchPlaylists({ search })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should search a local playlist', async function () {
- const search = servers[0].url + '/video-playlists/' + playlistServer1UUID
- const body = await command.searchPlaylists({ search })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
- expect(body.data[0].videosLength).to.equal(2)
- })
-
- it('Should search a local playlist with an alternative URL', async function () {
- const searches = [
- servers[0].url + '/videos/watch/playlist/' + playlistServer1UUID,
- servers[0].url + '/w/p/' + playlistServer1UUID
- ]
-
- for (const search of searches) {
- for (const token of [ undefined, servers[0].accessToken ]) {
- const body = await command.searchPlaylists({ search, token })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
- expect(body.data[0].videosLength).to.equal(2)
- }
- }
- })
-
- it('Should search a local playlist with a query in URL', async function () {
- const searches = [
- servers[0].url + '/videos/watch/playlist/' + playlistServer1UUID,
- servers[0].url + '/w/p/' + playlistServer1UUID
- ]
-
- for (const search of searches) {
- for (const token of [ undefined, servers[0].accessToken ]) {
- const body = await command.searchPlaylists({ search: search + '?param=1', token })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
- expect(body.data[0].videosLength).to.equal(2)
- }
- }
- })
-
- it('Should search a remote playlist', async function () {
- const searches = [
- servers[1].url + '/video-playlists/' + playlistServer2UUID,
- servers[1].url + '/videos/watch/playlist/' + playlistServer2UUID,
- servers[1].url + '/w/p/' + playlistServer2UUID
- ]
-
- for (const search of searches) {
- const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('playlist 1 on server 2')
- expect(body.data[0].videosLength).to.equal(1)
- }
- })
-
- it('Should not list this remote playlist', async function () {
- const body = await servers[0].playlists.list({ start: 0, count: 10 })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('playlist 1 on server 1')
- })
-
- it('Should update the playlist of server 2, and refresh it on server 1', async function () {
- this.timeout(60000)
-
- await servers[1].playlists.addElement({ playlistId: playlistServer2UUID, attributes: { videoId: video2Server2 } })
-
- await waitJobs(servers)
- // Expire playlist
- await wait(10000)
-
- // Will run refresh async
- const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
- await command.searchPlaylists({ search, token: servers[0].accessToken })
-
- // Wait refresh
- await wait(5000)
-
- const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.videosLength).to.equal(2)
- })
-
- it('Should delete playlist of server 2, and delete it on server 1', async function () {
- this.timeout(60000)
-
- await servers[1].playlists.delete({ playlistId: playlistServer2UUID })
-
- await waitJobs(servers)
- // Expiration
- await wait(10000)
-
- // Will run refresh async
- const search = servers[1].url + '/video-playlists/' + playlistServer2UUID
- await command.searchPlaylists({ search, token: servers[0].accessToken })
-
- // Wait refresh
- await wait(5000)
-
- const body = await command.searchPlaylists({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/search/search-activitypub-videos.ts b/server/tests/api/search/search-activitypub-videos.ts
deleted file mode 100644
index 4c7118422..000000000
--- a/server/tests/api/search/search-activitypub-videos.ts
+++ /dev/null
@@ -1,196 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test ActivityPub videos search', function () {
- let servers: PeerTubeServer[]
- let videoServer1UUID: string
- let videoServer2UUID: string
-
- let command: SearchCommand
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1 on server 1' } })
- videoServer1UUID = uuid
- }
-
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video 1 on server 2' } })
- videoServer2UUID = uuid
- }
-
- await waitJobs(servers)
-
- command = servers[0].search
- })
-
- it('Should not find a remote video', async function () {
- {
- const search = servers[1].url + '/videos/watch/43'
- const body = await command.searchVideos({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- // Without token
- const search = servers[1].url + '/videos/watch/' + videoServer2UUID
- const body = await command.searchVideos({ search })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should search a local video', async function () {
- const search = servers[0].url + '/videos/watch/' + videoServer1UUID
- const body = await command.searchVideos({ search })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('video 1 on server 1')
- })
-
- it('Should search a local video with an alternative URL', async function () {
- const search = servers[0].url + '/w/' + videoServer1UUID
- const body1 = await command.searchVideos({ search })
- const body2 = await command.searchVideos({ search, token: servers[0].accessToken })
-
- for (const body of [ body1, body2 ]) {
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('video 1 on server 1')
- }
- })
-
- it('Should search a local video with a query in URL', async function () {
- const searches = [
- servers[0].url + '/w/' + videoServer1UUID,
- servers[0].url + '/videos/watch/' + videoServer1UUID
- ]
-
- for (const search of searches) {
- for (const token of [ undefined, servers[0].accessToken ]) {
- const body = await command.searchVideos({ search: search + '?startTime=4', token })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('video 1 on server 1')
- }
- }
- })
-
- it('Should search a remote video', async function () {
- const searches = [
- servers[1].url + '/w/' + videoServer2UUID,
- servers[1].url + '/videos/watch/' + videoServer2UUID
- ]
-
- for (const search of searches) {
- const body = await command.searchVideos({ search, token: servers[0].accessToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('video 1 on server 2')
- }
- })
-
- it('Should not list this remote video', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('video 1 on server 1')
- })
-
- it('Should update video of server 2, and refresh it on server 1', async function () {
- this.timeout(120000)
-
- const channelAttributes = {
- name: 'super_channel',
- displayName: 'super channel'
- }
- const created = await servers[1].channels.create({ attributes: channelAttributes })
- const videoChannelId = created.id
-
- const attributes = {
- name: 'updated',
- tag: [ 'tag1', 'tag2' ],
- privacy: VideoPrivacy.UNLISTED,
- channelId: videoChannelId
- }
- await servers[1].videos.update({ id: videoServer2UUID, attributes })
-
- await waitJobs(servers)
- // Expire video
- await wait(10000)
-
- // Will run refresh async
- const search = servers[1].url + '/videos/watch/' + videoServer2UUID
- await command.searchVideos({ search, token: servers[0].accessToken })
-
- // Wait refresh
- await wait(5000)
-
- const body = await command.searchVideos({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const video = body.data[0]
- expect(video.name).to.equal('updated')
- expect(video.channel.name).to.equal('super_channel')
- expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
- })
-
- it('Should delete video of server 2, and delete it on server 1', async function () {
- this.timeout(120000)
-
- await servers[1].videos.remove({ id: videoServer2UUID })
-
- await waitJobs(servers)
- // Expire video
- await wait(10000)
-
- // Will run refresh async
- const search = servers[1].url + '/videos/watch/' + videoServer2UUID
- await command.searchVideos({ search, token: servers[0].accessToken })
-
- // Wait refresh
- await wait(5000)
-
- const body = await command.searchVideos({ search, token: servers[0].accessToken })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/search/search-channels.ts b/server/tests/api/search/search-channels.ts
deleted file mode 100644
index c6b098a93..000000000
--- a/server/tests/api/search/search-channels.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { VideoChannel } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- doubleFollow,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar
-} from '@shared/server-commands'
-
-describe('Test channels search', function () {
- let server: PeerTubeServer
- let remoteServer: PeerTubeServer
- let command: SearchCommand
-
- before(async function () {
- this.timeout(120000)
-
- const servers = await Promise.all([
- createSingleServer(1),
- createSingleServer(2)
- ])
- server = servers[0]
- remoteServer = servers[1]
-
- await setAccessTokensToServers([ server, remoteServer ])
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(server)
-
- await servers[1].config.disableTranscoding()
-
- {
- await server.users.create({ username: 'user1' })
- const channel = {
- name: 'squall_channel',
- displayName: 'Squall channel'
- }
- await server.channels.create({ attributes: channel })
- }
-
- {
- await remoteServer.users.create({ username: 'user1' })
- const channel = {
- name: 'zell_channel',
- displayName: 'Zell channel'
- }
- const { id } = await remoteServer.channels.create({ attributes: channel })
-
- await remoteServer.videos.upload({ attributes: { channelId: id } })
- }
-
- await doubleFollow(server, remoteServer)
-
- command = server.search
- })
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchChannels({ search: 'abc' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- {
- const search = {
- search: 'Squall',
- start: 0,
- count: 1
- }
- const body = await command.advancedChannelSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const channel: VideoChannel = body.data[0]
- expect(channel.name).to.equal('squall_channel')
- expect(channel.displayName).to.equal('Squall channel')
- }
-
- {
- const search = {
- search: 'Squall',
- start: 1,
- count: 1
- }
-
- const body = await command.advancedChannelSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should filter by host', async function () {
- {
- const search = { search: 'channel', host: remoteServer.host }
-
- const body = await command.advancedChannelSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('Zell channel')
- }
-
- {
- const search = { search: 'Sq', host: server.host }
-
- const body = await command.advancedChannelSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('Squall channel')
- }
-
- {
- const search = { search: 'Squall', host: 'example.com' }
-
- const body = await command.advancedChannelSearch({ search })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should filter by names', async function () {
- {
- const body = await command.advancedChannelSearch({ search: { handles: [ 'squall_channel', 'zell_channel' ] } })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('Squall channel')
- }
-
- {
- const body = await command.advancedChannelSearch({ search: { handles: [ 'squall_channel@' + server.host ] } })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].displayName).to.equal('Squall channel')
- }
-
- {
- const body = await command.advancedChannelSearch({ search: { handles: [ 'chocobozzz_channel' ] } })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await command.advancedChannelSearch({ search: { handles: [ 'squall_channel', 'zell_channel@' + remoteServer.host ] } })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
- expect(body.data[0].displayName).to.equal('Squall channel')
- expect(body.data[1].displayName).to.equal('Zell channel')
- }
- })
-
- after(async function () {
- await cleanupTests([ server, remoteServer ])
- })
-})
diff --git a/server/tests/api/search/search-index.ts b/server/tests/api/search/search-index.ts
deleted file mode 100644
index cbe628ccc..000000000
--- a/server/tests/api/search/search-index.ts
+++ /dev/null
@@ -1,432 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- BooleanBothQuery,
- VideoChannelsSearchQuery,
- VideoPlaylistPrivacy,
- VideoPlaylistsSearchQuery,
- VideoPlaylistType,
- VideosSearchQuery
-} from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, SearchCommand, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test index search', function () {
- const localVideoName = 'local video' + new Date().toISOString()
-
- let server: PeerTubeServer = null
- let command: SearchCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- await server.videos.upload({ attributes: { name: localVideoName } })
-
- command = server.search
- })
-
- describe('Default search', async function () {
-
- it('Should make a local videos search by default', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: false,
- disableLocalSearch: false
- }
- }
- }
- })
-
- const body = await command.searchVideos({ search: 'local video' })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal(localVideoName)
- })
-
- it('Should make a local channels search by default', async function () {
- const body = await command.searchChannels({ search: 'root' })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('root_channel')
- expect(body.data[0].host).to.equal(server.host)
- })
-
- it('Should make an index videos search by default', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: true,
- disableLocalSearch: false
- }
- }
- }
- })
-
- const body = await command.searchVideos({ search: 'local video' })
- expect(body.total).to.be.greaterThan(2)
- })
-
- it('Should make an index channels search by default', async function () {
- const body = await command.searchChannels({ search: 'root' })
- expect(body.total).to.be.greaterThan(2)
- })
- })
-
- describe('Videos search', async function () {
-
- async function check (search: VideosSearchQuery, exists = true) {
- const body = await command.advancedVideoSearch({ search })
-
- if (exists === false) {
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- return
- }
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const video = body.data[0]
-
- expect(video.name).to.equal('What is PeerTube?')
- expect(video.category.label).to.equal('Science & Technology')
- expect(video.licence.label).to.equal('Attribution - Share Alike')
- expect(video.privacy.label).to.equal('Public')
- expect(video.duration).to.equal(113)
- expect(video.thumbnailUrl.startsWith('https://framatube.org/static/thumbnails')).to.be.true
-
- expect(video.account.host).to.equal('framatube.org')
- expect(video.account.name).to.equal('framasoft')
- expect(video.account.url).to.equal('https://framatube.org/accounts/framasoft')
- expect(video.account.avatars.length).to.equal(2, 'Account should have one avatar image')
-
- expect(video.channel.host).to.equal('framatube.org')
- expect(video.channel.name).to.equal('joinpeertube')
- expect(video.channel.url).to.equal('https://framatube.org/video-channels/joinpeertube')
- expect(video.channel.avatars.length).to.equal(2, 'Channel should have one avatar image')
- }
-
- const baseSearch: VideosSearchQuery = {
- search: 'what is peertube',
- start: 0,
- count: 2,
- categoryOneOf: [ 15 ],
- licenceOneOf: [ 2 ],
- tagsAllOf: [ 'framasoft', 'peertube' ],
- startDate: '2018-10-01T10:50:46.396Z',
- endDate: '2018-10-01T10:55:46.396Z'
- }
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchVideos({ search: 'djidane'.repeat(50) })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a simple search and have results', async function () {
- const body = await command.searchVideos({ search: 'What is PeerTube' })
-
- expect(body.total).to.be.greaterThan(1)
- })
-
- it('Should make a simple search', async function () {
- await check(baseSearch)
- })
-
- it('Should search by start date', async function () {
- const search = { ...baseSearch, startDate: '2018-10-01T10:54:46.396Z' }
- await check(search, false)
- })
-
- it('Should search by tags', async function () {
- const search = { ...baseSearch, tagsAllOf: [ 'toto', 'framasoft' ] }
- await check(search, false)
- })
-
- it('Should search by duration', async function () {
- const search = { ...baseSearch, durationMin: 2000 }
- await check(search, false)
- })
-
- it('Should search by nsfw attribute', async function () {
- {
- const search = { ...baseSearch, nsfw: 'true' as BooleanBothQuery }
- await check(search, false)
- }
-
- {
- const search = { ...baseSearch, nsfw: 'false' as BooleanBothQuery }
- await check(search, true)
- }
-
- {
- const search = { ...baseSearch, nsfw: 'both' as BooleanBothQuery }
- await check(search, true)
- }
- })
-
- it('Should search by host', async function () {
- {
- const search = { ...baseSearch, host: 'example.com' }
- await check(search, false)
- }
-
- {
- const search = { ...baseSearch, host: 'framatube.org' }
- await check(search, true)
- }
- })
-
- it('Should search by uuids', async function () {
- const goodUUID = '9c9de5e8-0a1e-484a-b099-e80766180a6d'
- const goodShortUUID = 'kkGMgK9ZtnKfYAgnEtQxbv'
- const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
- const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
-
- {
- const uuidsMatrix = [
- [ goodUUID ],
- [ goodUUID, badShortUUID ],
- [ badShortUUID, goodShortUUID ],
- [ goodUUID, goodShortUUID ]
- ]
-
- for (const uuids of uuidsMatrix) {
- const search = { ...baseSearch, uuids }
- await check(search, true)
- }
- }
-
- {
- const uuidsMatrix = [
- [ badUUID ],
- [ badShortUUID ]
- ]
-
- for (const uuids of uuidsMatrix) {
- const search = { ...baseSearch, uuids }
- await check(search, false)
- }
- }
- })
-
- it('Should have a correct pagination', async function () {
- const search = {
- search: 'video',
- start: 0,
- count: 5
- }
-
- const body = await command.advancedVideoSearch({ search })
-
- expect(body.total).to.be.greaterThan(5)
- expect(body.data).to.have.lengthOf(5)
- })
-
- it('Should use the nsfw instance policy as default', async function () {
- let nsfwUUID: string
-
- {
- await server.config.updateCustomSubConfig({
- newConfig: {
- instance: { defaultNSFWPolicy: 'display' }
- }
- })
-
- const body = await command.searchVideos({ search: 'NSFW search index', sort: '-match' })
- expect(body.data).to.have.length.greaterThan(0)
-
- const video = body.data[0]
- expect(video.nsfw).to.be.true
-
- nsfwUUID = video.uuid
- }
-
- {
- await server.config.updateCustomSubConfig({
- newConfig: {
- instance: { defaultNSFWPolicy: 'do_not_list' }
- }
- })
-
- const body = await command.searchVideos({ search: 'NSFW search index', sort: '-match' })
-
- try {
- expect(body.data).to.have.lengthOf(0)
- } catch {
- const video = body.data[0]
-
- expect(video.uuid).not.equal(nsfwUUID)
- }
- }
- })
- })
-
- describe('Channels search', async function () {
-
- async function check (search: VideoChannelsSearchQuery, exists = true) {
- const body = await command.advancedChannelSearch({ search })
-
- if (exists === false) {
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- return
- }
-
- expect(body.total).to.be.greaterThan(0)
- expect(body.data).to.have.length.greaterThan(0)
-
- const videoChannel = body.data[0]
- expect(videoChannel.url).to.equal('https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8')
- expect(videoChannel.host).to.equal('framatube.org')
- expect(videoChannel.avatars.length).to.equal(2, 'Channel should have two avatar images')
- expect(videoChannel.displayName).to.exist
-
- expect(videoChannel.ownerAccount.url).to.equal('https://framatube.org/accounts/framasoft')
- expect(videoChannel.ownerAccount.name).to.equal('framasoft')
- expect(videoChannel.ownerAccount.host).to.equal('framatube.org')
- expect(videoChannel.ownerAccount.avatars.length).to.equal(2, 'Account should have two avatar images')
- }
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchChannels({ search: 'a'.repeat(500) })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- await check({ search: 'Framasoft', sort: 'createdAt' }, true)
- })
-
- it('Should make host search and have appropriate results', async function () {
- await check({ search: 'Framasoft videos', host: 'example.com' }, false)
- await check({ search: 'Framasoft videos', host: 'framatube.org' }, true)
- })
-
- it('Should make handles search and have appropriate results', async function () {
- await check({ handles: [ 'bf54d359-cfad-4935-9d45-9d6be93f63e8@framatube.org' ] }, true)
- await check({ handles: [ 'jeanine', 'bf54d359-cfad-4935-9d45-9d6be93f63e8@framatube.org' ] }, true)
- await check({ handles: [ 'jeanine', 'chocobozzz_channel2@peertube2.cpy.re' ] }, false)
- })
-
- it('Should have a correct pagination', async function () {
- const body = await command.advancedChannelSearch({ search: { search: 'root', start: 0, count: 2 } })
-
- expect(body.total).to.be.greaterThan(2)
- expect(body.data).to.have.lengthOf(2)
- })
- })
-
- describe('Playlists search', async function () {
-
- async function check (search: VideoPlaylistsSearchQuery, exists = true) {
- const body = await command.advancedPlaylistSearch({ search })
-
- if (exists === false) {
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- return
- }
-
- expect(body.total).to.be.greaterThan(0)
- expect(body.data).to.have.length.greaterThan(0)
-
- const videoPlaylist = body.data[0]
-
- expect(videoPlaylist.url).to.equal('https://peertube2.cpy.re/videos/watch/playlist/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a')
- expect(videoPlaylist.thumbnailUrl).to.exist
- expect(videoPlaylist.embedUrl).to.equal('https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a')
-
- expect(videoPlaylist.type.id).to.equal(VideoPlaylistType.REGULAR)
- expect(videoPlaylist.privacy.id).to.equal(VideoPlaylistPrivacy.PUBLIC)
- expect(videoPlaylist.videosLength).to.exist
-
- expect(videoPlaylist.createdAt).to.exist
- expect(videoPlaylist.updatedAt).to.exist
-
- expect(videoPlaylist.uuid).to.equal('73804a40-da9a-40c2-b1eb-2c6d9eec8f0a')
- expect(videoPlaylist.displayName).to.exist
-
- expect(videoPlaylist.ownerAccount.url).to.equal('https://peertube2.cpy.re/accounts/chocobozzz')
- expect(videoPlaylist.ownerAccount.name).to.equal('chocobozzz')
- expect(videoPlaylist.ownerAccount.host).to.equal('peertube2.cpy.re')
- expect(videoPlaylist.ownerAccount.avatars.length).to.equal(2, 'Account should have two avatar images')
-
- expect(videoPlaylist.videoChannel.url).to.equal('https://peertube2.cpy.re/video-channels/chocobozzz_channel')
- expect(videoPlaylist.videoChannel.name).to.equal('chocobozzz_channel')
- expect(videoPlaylist.videoChannel.host).to.equal('peertube2.cpy.re')
- expect(videoPlaylist.videoChannel.avatars.length).to.equal(2, 'Channel should have two avatar images')
- }
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchPlaylists({ search: 'a'.repeat(500) })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- await check({ search: 'E2E playlist', sort: '-match' }, true)
- })
-
- it('Should make host search and have appropriate results', async function () {
- await check({ search: 'E2E playlist', host: 'example.com' }, false)
- await check({ search: 'E2E playlist', host: 'peertube2.cpy.re', sort: '-match' }, true)
- })
-
- it('Should make a search by uuids and have appropriate results', async function () {
- const goodUUID = '73804a40-da9a-40c2-b1eb-2c6d9eec8f0a'
- const goodShortUUID = 'fgei1ws1oa6FCaJ2qZPG29'
- const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
- const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
-
- {
- const uuidsMatrix = [
- [ goodUUID ],
- [ goodUUID, badShortUUID ],
- [ badShortUUID, goodShortUUID ],
- [ goodUUID, goodShortUUID ]
- ]
-
- for (const uuids of uuidsMatrix) {
- const search = { search: 'E2E playlist', sort: '-match', uuids }
- await check(search, true)
- }
- }
-
- {
- const uuidsMatrix = [
- [ badUUID ],
- [ badShortUUID ]
- ]
-
- for (const uuids of uuidsMatrix) {
- const search = { search: 'E2E playlist', sort: '-match', uuids }
- await check(search, false)
- }
- }
- })
-
- it('Should have a correct pagination', async function () {
- const body = await command.advancedChannelSearch({ search: { search: 'root', start: 0, count: 2 } })
-
- expect(body.total).to.be.greaterThan(2)
- expect(body.data).to.have.lengthOf(2)
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/search/search-playlists.ts b/server/tests/api/search/search-playlists.ts
deleted file mode 100644
index a357674c2..000000000
--- a/server/tests/api/search/search-playlists.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { VideoPlaylistPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- doubleFollow,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-
-describe('Test playlists search', function () {
- let server: PeerTubeServer
- let remoteServer: PeerTubeServer
- let command: SearchCommand
- let playlistUUID: string
- let playlistShortUUID: string
-
- before(async function () {
- this.timeout(120000)
-
- const servers = await Promise.all([
- createSingleServer(1),
- createSingleServer(2)
- ])
- server = servers[0]
- remoteServer = servers[1]
-
- await setAccessTokensToServers([ remoteServer, server ])
- await setDefaultVideoChannel([ remoteServer, server ])
- await setDefaultChannelAvatar([ remoteServer, server ])
- await setDefaultAccountAvatar([ remoteServer, server ])
-
- await servers[1].config.disableTranscoding()
-
- {
- const videoId = (await server.videos.upload()).uuid
-
- const attributes = {
- displayName: 'Dr. Kenzo Tenma hospital videos',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id
- }
- const created = await server.playlists.create({ attributes })
- playlistUUID = created.uuid
- playlistShortUUID = created.shortUUID
-
- await server.playlists.addElement({ playlistId: created.id, attributes: { videoId } })
- }
-
- {
- const videoId = (await remoteServer.videos.upload()).uuid
-
- const attributes = {
- displayName: 'Johan & Anna Libert music videos',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: remoteServer.store.channel.id
- }
- const created = await remoteServer.playlists.create({ attributes })
-
- await remoteServer.playlists.addElement({ playlistId: created.id, attributes: { videoId } })
- }
-
- {
- const attributes = {
- displayName: 'Inspector Lunge playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id
- }
- await server.playlists.create({ attributes })
- }
-
- await doubleFollow(server, remoteServer)
-
- command = server.search
- })
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchPlaylists({ search: 'abc' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a search and have results', async function () {
- {
- const search = {
- search: 'tenma',
- start: 0,
- count: 1
- }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.displayName).to.equal('Dr. Kenzo Tenma hospital videos')
- expect(playlist.url).to.equal(server.url + '/video-playlists/' + playlist.uuid)
- }
-
- {
- const search = {
- search: 'Anna Livert music',
- start: 0,
- count: 1
- }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.displayName).to.equal('Johan & Anna Libert music videos')
- }
- })
-
- it('Should filter by host', async function () {
- {
- const search = { search: 'tenma', host: server.host }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.displayName).to.equal('Dr. Kenzo Tenma hospital videos')
- }
-
- {
- const search = { search: 'Anna', host: 'example.com' }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const search = { search: 'video', host: remoteServer.host }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.displayName).to.equal('Johan & Anna Libert music videos')
- }
- })
-
- it('Should filter by UUIDs', async function () {
- for (const uuid of [ playlistUUID, playlistShortUUID ]) {
- const body = await command.advancedPlaylistSearch({ search: { uuids: [ uuid ] } })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].displayName).to.equal('Dr. Kenzo Tenma hospital videos')
- }
-
- {
- const body = await command.advancedPlaylistSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should not display playlists without videos', async function () {
- const search = {
- search: 'Lunge',
- start: 0,
- count: 1
- }
- const body = await command.advancedPlaylistSearch({ search })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests([ server, remoteServer ])
- })
-})
diff --git a/server/tests/api/search/search-videos.ts b/server/tests/api/search/search-videos.ts
deleted file mode 100644
index f7f50147d..000000000
--- a/server/tests/api/search/search-videos.ts
+++ /dev/null
@@ -1,568 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- doubleFollow,
- PeerTubeServer,
- SearchCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- setDefaultVideoChannel,
- stopFfmpeg
-} from '@shared/server-commands'
-
-describe('Test videos search', function () {
- let server: PeerTubeServer
- let remoteServer: PeerTubeServer
- let startDate: string
- let videoUUID: string
- let videoShortUUID: string
-
- let command: SearchCommand
-
- before(async function () {
- this.timeout(360000)
-
- const servers = await Promise.all([
- createSingleServer(1),
- createSingleServer(2)
- ])
- server = servers[0]
- remoteServer = servers[1]
-
- await setAccessTokensToServers([ server, remoteServer ])
- await setDefaultVideoChannel([ server, remoteServer ])
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(servers)
-
- {
- const attributes1 = {
- name: '1111 2222 3333',
- fixture: '60fps_720p_small.mp4', // 2 seconds
- category: 1,
- licence: 1,
- nsfw: false,
- language: 'fr'
- }
- await server.videos.upload({ attributes: attributes1 })
-
- const attributes2 = { ...attributes1, name: attributes1.name + ' - 2', fixture: 'video_short.mp4' }
- await server.videos.upload({ attributes: attributes2 })
-
- {
- const attributes3 = { ...attributes1, name: attributes1.name + ' - 3', language: undefined }
- const { id, uuid, shortUUID } = await server.videos.upload({ attributes: attributes3 })
- videoUUID = uuid
- videoShortUUID = shortUUID
-
- await server.captions.add({
- language: 'en',
- videoId: id,
- fixture: 'subtitle-good2.vtt',
- mimeType: 'application/octet-stream'
- })
-
- await server.captions.add({
- language: 'aa',
- videoId: id,
- fixture: 'subtitle-good2.vtt',
- mimeType: 'application/octet-stream'
- })
- }
-
- const attributes4 = { ...attributes1, name: attributes1.name + ' - 4', language: 'pl', nsfw: true }
- await server.videos.upload({ attributes: attributes4 })
-
- await wait(1000)
-
- startDate = new Date().toISOString()
-
- const attributes5 = { ...attributes1, name: attributes1.name + ' - 5', licence: 2, language: undefined }
- await server.videos.upload({ attributes: attributes5 })
-
- const attributes6 = { ...attributes1, name: attributes1.name + ' - 6', tags: [ 't1', 't2' ] }
- await server.videos.upload({ attributes: attributes6 })
-
- const attributes7 = { ...attributes1, name: attributes1.name + ' - 7', originallyPublishedAt: '2019-02-12T09:58:08.286Z' }
- await server.videos.upload({ attributes: attributes7 })
-
- const attributes8 = { ...attributes1, name: attributes1.name + ' - 8', licence: 4 }
- await server.videos.upload({ attributes: attributes8 })
- }
-
- {
- const attributes = {
- name: '3333 4444 5555',
- fixture: 'video_short.mp4',
- category: 2,
- licence: 2,
- language: 'en'
- }
- await server.videos.upload({ attributes })
-
- await server.videos.upload({ attributes: { ...attributes, name: attributes.name + ' duplicate' } })
- }
-
- {
- const attributes = {
- name: '6666 7777 8888',
- fixture: 'video_short.mp4',
- category: 3,
- licence: 3,
- language: 'pl'
- }
- await server.videos.upload({ attributes })
- }
-
- {
- const attributes1 = {
- name: '9999',
- tags: [ 'aaaa', 'bbbb', 'cccc' ],
- category: 1
- }
- await server.videos.upload({ attributes: attributes1 })
- await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
-
- await server.videos.upload({ attributes: { ...attributes1, tags: [ 'cccc', 'dddd' ] } })
- await server.videos.upload({ attributes: { ...attributes1, tags: [ 'eeee', 'ffff' ] } })
- }
-
- {
- const attributes1 = {
- name: 'aaaa 2',
- category: 1
- }
- await server.videos.upload({ attributes: attributes1 })
- await server.videos.upload({ attributes: { ...attributes1, category: 2 } })
- }
-
- {
- await remoteServer.videos.upload({ attributes: { name: 'remote video 1' } })
- await remoteServer.videos.upload({ attributes: { name: 'remote video 2' } })
- }
-
- await doubleFollow(server, remoteServer)
-
- command = server.search
- })
-
- it('Should make a simple search and not have results', async function () {
- const body = await command.searchVideos({ search: 'abc' })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should make a simple search and have results', async function () {
- const body = await command.searchVideos({ search: '4444 5555 duplicate' })
-
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
-
- // bestmatch
- expect(videos[0].name).to.equal('3333 4444 5555 duplicate')
- expect(videos[1].name).to.equal('3333 4444 5555')
- })
-
- it('Should make a search on tags too, and have results', async function () {
- const search = {
- search: 'aaaa',
- categoryOneOf: [ 1 ]
- }
- const body = await command.advancedVideoSearch({ search })
-
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
-
- // bestmatch
- expect(videos[0].name).to.equal('aaaa 2')
- expect(videos[1].name).to.equal('9999')
- })
-
- it('Should filter on tags without a search', async function () {
- const search = {
- tagsAllOf: [ 'bbbb' ]
- }
- const body = await command.advancedVideoSearch({ search })
-
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
-
- expect(videos[0].name).to.equal('9999')
- expect(videos[1].name).to.equal('9999')
- })
-
- it('Should filter on category without a search', async function () {
- const search = {
- categoryOneOf: [ 3 ]
- }
- const body = await command.advancedVideoSearch({ search })
-
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
-
- expect(videos[0].name).to.equal('6666 7777 8888')
- })
-
- it('Should search by tags (one of)', async function () {
- const query = {
- search: '9999',
- categoryOneOf: [ 1 ],
- tagsOneOf: [ 'aAaa', 'ffff' ]
- }
-
- {
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(2)
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, tagsOneOf: [ 'blabla' ] } })
- expect(body.total).to.equal(0)
- }
- })
-
- it('Should search by tags (all of)', async function () {
- const query = {
- search: '9999',
- categoryOneOf: [ 1 ],
- tagsAllOf: [ 'CCcc' ]
- }
-
- {
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(2)
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'blAbla' ] } })
- expect(body.total).to.equal(0)
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, tagsAllOf: [ 'bbbb', 'CCCC' ] } })
- expect(body.total).to.equal(1)
- }
- })
-
- it('Should search by category', async function () {
- const query = {
- search: '6666',
- categoryOneOf: [ 3 ]
- }
-
- {
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('6666 7777 8888')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, categoryOneOf: [ 2 ] } })
- expect(body.total).to.equal(0)
- }
- })
-
- it('Should search by licence', async function () {
- const query = {
- search: '4444 5555',
- licenceOneOf: [ 2 ]
- }
-
- {
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(2)
- expect(body.data[0].name).to.equal('3333 4444 5555')
- expect(body.data[1].name).to.equal('3333 4444 5555 duplicate')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, licenceOneOf: [ 3 ] } })
- expect(body.total).to.equal(0)
- }
- })
-
- it('Should search by languages', async function () {
- const query = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'en' ]
- }
-
- {
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(2)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
- expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'pl', 'en', '_unknown' ] } })
- expect(body.total).to.equal(3)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
- expect(body.data[1].name).to.equal('1111 2222 3333 - 4')
- expect(body.data[2].name).to.equal('1111 2222 3333 - 5')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { ...query, languageOneOf: [ 'eo' ] } })
- expect(body.total).to.equal(0)
- }
- })
-
- it('Should search by start date', async function () {
- const query = {
- search: '1111 2222 3333',
- startDate
- }
-
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos[0].name).to.equal('1111 2222 3333 - 5')
- expect(videos[1].name).to.equal('1111 2222 3333 - 6')
- expect(videos[2].name).to.equal('1111 2222 3333 - 7')
- expect(videos[3].name).to.equal('1111 2222 3333 - 8')
- })
-
- it('Should make an advanced search', async function () {
- const query = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'fr' ],
- durationMax: 4,
- nsfw: 'false' as 'false',
- licenceOneOf: [ 1, 4 ]
- }
-
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos[0].name).to.equal('1111 2222 3333')
- expect(videos[1].name).to.equal('1111 2222 3333 - 6')
- expect(videos[2].name).to.equal('1111 2222 3333 - 7')
- expect(videos[3].name).to.equal('1111 2222 3333 - 8')
- })
-
- it('Should make an advanced search and sort results', async function () {
- const query = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'fr' ],
- durationMax: 4,
- nsfw: 'false' as 'false',
- licenceOneOf: [ 1, 4 ],
- sort: '-name'
- }
-
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos[0].name).to.equal('1111 2222 3333 - 8')
- expect(videos[1].name).to.equal('1111 2222 3333 - 7')
- expect(videos[2].name).to.equal('1111 2222 3333 - 6')
- expect(videos[3].name).to.equal('1111 2222 3333')
- })
-
- it('Should make an advanced search and only show the first result', async function () {
- const query = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'fr' ],
- durationMax: 4,
- nsfw: 'false' as 'false',
- licenceOneOf: [ 1, 4 ],
- sort: '-name',
- start: 0,
- count: 1
- }
-
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos[0].name).to.equal('1111 2222 3333 - 8')
- })
-
- it('Should make an advanced search and only show the last result', async function () {
- const query = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'fr' ],
- durationMax: 4,
- nsfw: 'false' as 'false',
- licenceOneOf: [ 1, 4 ],
- sort: '-name',
- start: 3,
- count: 1
- }
-
- const body = await command.advancedVideoSearch({ search: query })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos[0].name).to.equal('1111 2222 3333')
- })
-
- it('Should search on originally published date', async function () {
- const baseQuery = {
- search: '1111 2222 3333',
- languageOneOf: [ 'pl', 'fr' ],
- durationMax: 4,
- nsfw: 'false' as 'false',
- licenceOneOf: [ 1, 4 ]
- }
-
- {
- const query = { ...baseQuery, originallyPublishedStartDate: '2019-02-11T09:58:08.286Z' }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
- }
-
- {
- const query = { ...baseQuery, originallyPublishedEndDate: '2019-03-11T09:58:08.286Z' }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
- }
-
- {
- const query = { ...baseQuery, originallyPublishedEndDate: '2019-01-11T09:58:08.286Z' }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(0)
- }
-
- {
- const query = { ...baseQuery, originallyPublishedStartDate: '2019-03-11T09:58:08.286Z' }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(0)
- }
-
- {
- const query = {
- ...baseQuery,
- originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
- originallyPublishedEndDate: '2019-01-10T09:58:08.286Z'
- }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(0)
- }
-
- {
- const query = {
- ...baseQuery,
- originallyPublishedStartDate: '2019-01-11T09:58:08.286Z',
- originallyPublishedEndDate: '2019-04-11T09:58:08.286Z'
- }
- const body = await command.advancedVideoSearch({ search: query })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 7')
- }
- })
-
- it('Should search by UUID', async function () {
- const search = videoUUID
- const body = await command.advancedVideoSearch({ search: { search } })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
- })
-
- it('Should filter by UUIDs', async function () {
- for (const uuid of [ videoUUID, videoShortUUID ]) {
- const body = await command.advancedVideoSearch({ search: { uuids: [ uuid ] } })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('1111 2222 3333 - 3')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { uuids: [ 'dfd70b83-639f-4980-94af-304a56ab4b35' ] } })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should search by host', async function () {
- {
- const body = await command.advancedVideoSearch({ search: { search: '6666 7777 8888', host: server.host } })
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('6666 7777 8888')
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { search: '1111', host: 'example.com' } })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { search: 'remote', host: remoteServer.host } })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
- expect(body.data[0].name).to.equal('remote video 1')
- expect(body.data[1].name).to.equal('remote video 2')
- }
- })
-
- it('Should search by live', async function () {
- this.timeout(120000)
-
- {
- const newConfig = {
- search: {
- searchIndex: { enabled: false }
- },
- live: { enabled: true }
- }
- await server.config.updateCustomSubConfig({ newConfig })
- }
-
- {
- const body = await command.advancedVideoSearch({ search: { isLive: true } })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const liveCommand = server.live
-
- const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.store.channel.id }
- const live = await liveCommand.create({ fields: liveAttributes })
-
- const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
- await liveCommand.waitUntilPublished({ videoId: live.id })
-
- const body = await command.advancedVideoSearch({ search: { isLive: true } })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('live')
-
- await stopFfmpeg(ffmpegCommand)
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/auto-follows.ts b/server/tests/api/server/auto-follows.ts
deleted file mode 100644
index 6ce1a3799..000000000
--- a/server/tests/api/server/auto-follows.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { MockInstancesIndex } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { cleanupTests, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands'
-
-async function checkFollow (follower: PeerTubeServer, following: PeerTubeServer, exists: boolean) {
- {
- const body = await following.follows.getFollowers({ start: 0, count: 5, sort: '-createdAt' })
- const follow = body.data.find(f => f.follower.host === follower.host && f.state === 'accepted')
-
- if (exists === true) expect(follow, `Follower ${follower.url} should exist on ${following.url}`).to.exist
- else expect(follow, `Follower ${follower.url} should not exist on ${following.url}`).to.be.undefined
- }
-
- {
- const body = await follower.follows.getFollowings({ start: 0, count: 5, sort: '-createdAt' })
- const follow = body.data.find(f => f.following.host === following.host && f.state === 'accepted')
-
- if (exists === true) expect(follow, `Following ${following.url} should exist on ${follower.url}`).to.exist
- else expect(follow, `Following ${following.url} should not exist on ${follower.url}`).to.be.undefined
- }
-}
-
-async function server1Follows2 (servers: PeerTubeServer[]) {
- await servers[0].follows.follow({ hosts: [ servers[1].host ] })
-
- await waitJobs(servers)
-}
-
-async function resetFollows (servers: PeerTubeServer[]) {
- try {
- await servers[0].follows.unfollow({ target: servers[1] })
- await servers[1].follows.unfollow({ target: servers[0] })
- } catch { /* empty */
- }
-
- await waitJobs(servers)
-
- await checkFollow(servers[0], servers[1], false)
- await checkFollow(servers[1], servers[0], false)
-}
-
-describe('Test auto follows', function () {
- let servers: PeerTubeServer[] = []
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- })
-
- describe('Auto follow back', function () {
-
- it('Should not auto follow back if the option is not enabled', async function () {
- this.timeout(15000)
-
- await server1Follows2(servers)
-
- await checkFollow(servers[0], servers[1], true)
- await checkFollow(servers[1], servers[0], false)
-
- await resetFollows(servers)
- })
-
- it('Should auto follow back on auto accept if the option is enabled', async function () {
- this.timeout(15000)
-
- const config = {
- followings: {
- instance: {
- autoFollowBack: { enabled: true }
- }
- }
- }
- await servers[1].config.updateCustomSubConfig({ newConfig: config })
-
- await server1Follows2(servers)
-
- await checkFollow(servers[0], servers[1], true)
- await checkFollow(servers[1], servers[0], true)
-
- await resetFollows(servers)
- })
-
- it('Should wait the acceptation before auto follow back', async function () {
- this.timeout(30000)
-
- const config = {
- followings: {
- instance: {
- autoFollowBack: { enabled: true }
- }
- },
- followers: {
- instance: {
- manualApproval: true
- }
- }
- }
- await servers[1].config.updateCustomSubConfig({ newConfig: config })
-
- await server1Follows2(servers)
-
- await checkFollow(servers[0], servers[1], false)
- await checkFollow(servers[1], servers[0], false)
-
- await servers[1].follows.acceptFollower({ follower: 'peertube@' + servers[0].host })
- await waitJobs(servers)
-
- await checkFollow(servers[0], servers[1], true)
- await checkFollow(servers[1], servers[0], true)
-
- await resetFollows(servers)
-
- config.followings.instance.autoFollowBack.enabled = false
- config.followers.instance.manualApproval = false
- await servers[1].config.updateCustomSubConfig({ newConfig: config })
- })
- })
-
- describe('Auto follow index', function () {
- const instanceIndexServer = new MockInstancesIndex()
- let port: number
-
- before(async function () {
- port = await instanceIndexServer.initialize()
- })
-
- it('Should not auto follow index if the option is not enabled', async function () {
- this.timeout(30000)
-
- await wait(5000)
- await waitJobs(servers)
-
- await checkFollow(servers[0], servers[1], false)
- await checkFollow(servers[1], servers[0], false)
- })
-
- it('Should auto follow the index', async function () {
- this.timeout(30000)
-
- instanceIndexServer.addInstance(servers[1].host)
-
- const config = {
- followings: {
- instance: {
- autoFollowIndex: {
- indexUrl: `http://127.0.0.1:${port}/api/v1/instances/hosts`,
- enabled: true
- }
- }
- }
- }
- await servers[0].config.updateCustomSubConfig({ newConfig: config })
-
- await wait(5000)
- await waitJobs(servers)
-
- await checkFollow(servers[0], servers[1], true)
-
- await resetFollows(servers)
- })
-
- it('Should follow new added instances in the index but not old ones', async function () {
- this.timeout(30000)
-
- instanceIndexServer.addInstance(servers[2].host)
-
- await wait(5000)
- await waitJobs(servers)
-
- await checkFollow(servers[0], servers[1], false)
- await checkFollow(servers[0], servers[2], true)
- })
-
- after(async function () {
- await instanceIndexServer.terminate()
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/bulk.ts b/server/tests/api/server/bulk.ts
deleted file mode 100644
index 66d791a0f..000000000
--- a/server/tests/api/server/bulk.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- BulkCommand,
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test bulk actions', function () {
- const commentsUser3: { videoId: number, commentId: number }[] = []
-
- let servers: PeerTubeServer[] = []
- let user1Token: string
- let user2Token: string
- let user3Token: string
-
- let bulkCommand: BulkCommand
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- {
- const user = { username: 'user1', password: 'password' }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- user1Token = await servers[0].login.getAccessToken(user)
- }
-
- {
- const user = { username: 'user2', password: 'password' }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- user2Token = await servers[0].login.getAccessToken(user)
- }
-
- {
- const user = { username: 'user3', password: 'password' }
- await servers[1].users.create({ username: user.username, password: user.password })
-
- user3Token = await servers[1].login.getAccessToken(user)
- }
-
- await doubleFollow(servers[0], servers[1])
-
- bulkCommand = new BulkCommand(servers[0])
- })
-
- describe('Bulk remove comments', function () {
- async function checkInstanceCommentsRemoved () {
- {
- const { data } = await servers[0].videos.list()
-
- // Server 1 should not have these comments anymore
- for (const video of data) {
- const { data } = await servers[0].comments.listThreads({ videoId: video.id })
- const comment = data.find(c => c.text === 'comment by user 3')
-
- expect(comment).to.not.exist
- }
- }
-
- {
- const { data } = await servers[1].videos.list()
-
- // Server 1 should not have these comments on videos of server 1
- for (const video of data) {
- const { data } = await servers[1].comments.listThreads({ videoId: video.id })
- const comment = data.find(c => c.text === 'comment by user 3')
-
- if (video.account.host === servers[0].host) {
- expect(comment).to.not.exist
- } else {
- expect(comment).to.exist
- }
- }
- }
- }
-
- before(async function () {
- this.timeout(240000)
-
- await servers[0].videos.upload({ attributes: { name: 'video 1 server 1' } })
- await servers[0].videos.upload({ attributes: { name: 'video 2 server 1' } })
- await servers[0].videos.upload({ token: user1Token, attributes: { name: 'video 3 server 1' } })
-
- await servers[1].videos.upload({ attributes: { name: 'video 1 server 2' } })
-
- await waitJobs(servers)
-
- {
- const { data } = await servers[0].videos.list()
- for (const video of data) {
- await servers[0].comments.createThread({ videoId: video.id, text: 'comment by root server 1' })
- await servers[0].comments.createThread({ token: user1Token, videoId: video.id, text: 'comment by user 1' })
- await servers[0].comments.createThread({ token: user2Token, videoId: video.id, text: 'comment by user 2' })
- }
- }
-
- {
- const { data } = await servers[1].videos.list()
-
- for (const video of data) {
- await servers[1].comments.createThread({ videoId: video.id, text: 'comment by root server 2' })
-
- const comment = await servers[1].comments.createThread({ token: user3Token, videoId: video.id, text: 'comment by user 3' })
- commentsUser3.push({ videoId: video.id, commentId: comment.id })
- }
- }
-
- await waitJobs(servers)
- })
-
- it('Should delete comments of an account on my videos', async function () {
- this.timeout(60000)
-
- await bulkCommand.removeCommentsOf({
- token: user1Token,
- attributes: {
- accountName: 'user2',
- scope: 'my-videos'
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- for (const video of data) {
- const { data } = await server.comments.listThreads({ videoId: video.id })
- const comment = data.find(c => c.text === 'comment by user 2')
-
- if (video.name === 'video 3 server 1') expect(comment).to.not.exist
- else expect(comment).to.exist
- }
- }
- })
-
- it('Should delete comments of an account on the instance', async function () {
- this.timeout(60000)
-
- await bulkCommand.removeCommentsOf({
- attributes: {
- accountName: 'user3@' + servers[1].host,
- scope: 'instance'
- }
- })
-
- await waitJobs(servers)
-
- await checkInstanceCommentsRemoved()
- })
-
- it('Should not re create the comment on video update', async function () {
- this.timeout(60000)
-
- for (const obj of commentsUser3) {
- await servers[1].comments.addReply({
- token: user3Token,
- videoId: obj.videoId,
- toCommentId: obj.commentId,
- text: 'comment by user 3 bis'
- })
- }
-
- await waitJobs(servers)
-
- await checkInstanceCommentsRemoved()
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/config-defaults.ts b/server/tests/api/server/config-defaults.ts
deleted file mode 100644
index 041032f2b..000000000
--- a/server/tests/api/server/config-defaults.ts
+++ /dev/null
@@ -1,288 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { VideoDetails, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/server-commands'
-
-describe('Test config defaults', function () {
- let server: PeerTubeServer
- let channelId: number
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- channelId = server.store.channel.id
- })
-
- describe('Default publish values', function () {
-
- before(async function () {
- const overrideConfig = {
- defaults: {
- publish: {
- comments_enabled: false,
- download_enabled: false,
- privacy: VideoPrivacy.INTERNAL,
- licence: 4
- }
- }
- }
-
- await server.kill()
- await server.run(overrideConfig)
- })
-
- const attributes = {
- name: 'video',
- downloadEnabled: undefined,
- commentsEnabled: undefined,
- licence: undefined,
- privacy: VideoPrivacy.PUBLIC // Privacy is mandatory for server
- }
-
- function checkVideo (video: VideoDetails) {
- expect(video.downloadEnabled).to.be.false
- expect(video.commentsEnabled).to.be.false
- expect(video.licence.id).to.equal(4)
- }
-
- before(async function () {
- await server.config.disableTranscoding()
- await server.config.enableImports()
- await server.config.enableLive({ allowReplay: false, transcoding: false })
- })
-
- it('Should have the correct server configuration', async function () {
- const config = await server.config.getConfig()
-
- expect(config.defaults.publish.commentsEnabled).to.be.false
- expect(config.defaults.publish.downloadEnabled).to.be.false
- expect(config.defaults.publish.licence).to.equal(4)
- expect(config.defaults.publish.privacy).to.equal(VideoPrivacy.INTERNAL)
- })
-
- it('Should respect default values when uploading a video', async function () {
- for (const mode of [ 'legacy' as 'legacy', 'resumable' as 'resumable' ]) {
- const { id } = await server.videos.upload({ attributes, mode })
-
- const video = await server.videos.get({ id })
- checkVideo(video)
- }
- })
-
- it('Should respect default values when importing a video using URL', async function () {
- const { video: { id } } = await server.imports.importVideo({
- attributes: {
- ...attributes,
- channelId,
- targetUrl: FIXTURE_URLS.goodVideo
- }
- })
-
- const video = await server.videos.get({ id })
- checkVideo(video)
- })
-
- it('Should respect default values when importing a video using magnet URI', async function () {
- const { video: { id } } = await server.imports.importVideo({
- attributes: {
- ...attributes,
- channelId,
- magnetUri: FIXTURE_URLS.magnet
- }
- })
-
- const video = await server.videos.get({ id })
- checkVideo(video)
- })
-
- it('Should respect default values when creating a live', async function () {
- const { id } = await server.live.create({
- fields: {
- ...attributes,
- channelId
- }
- })
-
- const video = await server.videos.get({ id })
- checkVideo(video)
- })
- })
-
- describe('Default P2P values', function () {
-
- describe('Webapp default value', function () {
-
- before(async function () {
- const overrideConfig = {
- defaults: {
- p2p: {
- webapp: {
- enabled: false
- }
- }
- }
- }
-
- await server.kill()
- await server.run(overrideConfig)
- })
-
- it('Should have appropriate P2P config', async function () {
- const config = await server.config.getConfig()
-
- expect(config.defaults.p2p.webapp.enabled).to.be.false
- expect(config.defaults.p2p.embed.enabled).to.be.true
- })
-
- it('Should create a user with this default setting', async function () {
- await server.users.create({ username: 'user_p2p_1' })
- const userToken = await server.login.getAccessToken('user_p2p_1')
-
- const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(p2pEnabled).to.be.false
- })
-
- it('Should register a user with this default setting', async function () {
- await server.registrations.register({ username: 'user_p2p_2' })
-
- const userToken = await server.login.getAccessToken('user_p2p_2')
-
- const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(p2pEnabled).to.be.false
- })
- })
-
- describe('Embed default value', function () {
-
- before(async function () {
- const overrideConfig = {
- defaults: {
- p2p: {
- embed: {
- enabled: false
- }
- }
- },
- signup: {
- limit: 15
- }
- }
-
- await server.kill()
- await server.run(overrideConfig)
- })
-
- it('Should have appropriate P2P config', async function () {
- const config = await server.config.getConfig()
-
- expect(config.defaults.p2p.webapp.enabled).to.be.true
- expect(config.defaults.p2p.embed.enabled).to.be.false
- })
-
- it('Should create a user with this default setting', async function () {
- await server.users.create({ username: 'user_p2p_3' })
- const userToken = await server.login.getAccessToken('user_p2p_3')
-
- const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(p2pEnabled).to.be.true
- })
-
- it('Should register a user with this default setting', async function () {
- await server.registrations.register({ username: 'user_p2p_4' })
-
- const userToken = await server.login.getAccessToken('user_p2p_4')
-
- const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(p2pEnabled).to.be.true
- })
- })
- })
-
- describe('Default user attributes', function () {
- it('Should create a user and register a user with the default config', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- user: {
- history: {
- videos: {
- enabled: true
- }
- },
- videoQuota : -1,
- videoQuotaDaily: -1
- },
- signup: {
- enabled: true,
- requiresApproval: false
- }
- }
- })
-
- const config = await server.config.getConfig()
-
- expect(config.user.videoQuota).to.equal(-1)
- expect(config.user.videoQuotaDaily).to.equal(-1)
-
- const user1Token = await server.users.generateUserAndToken('user1')
- const user1 = await server.users.getMyInfo({ token: user1Token })
-
- const user = { displayName: 'super user 2', username: 'user2', password: 'super password' }
- const channel = { name: 'my_user_2_channel', displayName: 'my channel' }
- await server.registrations.register({ ...user, channel })
- const user2Token = await server.login.getAccessToken(user)
- const user2 = await server.users.getMyInfo({ token: user2Token })
-
- for (const user of [ user1, user2 ]) {
- expect(user.videosHistoryEnabled).to.be.true
- expect(user.videoQuota).to.equal(-1)
- expect(user.videoQuotaDaily).to.equal(-1)
- }
- })
-
- it('Should update config and create a user and register a user with the new default config', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- user: {
- history: {
- videos: {
- enabled: false
- }
- },
- videoQuota : 5242881,
- videoQuotaDaily: 318742
- },
- signup: {
- enabled: true,
- requiresApproval: false
- }
- }
- })
-
- const user3Token = await server.users.generateUserAndToken('user3')
- const user3 = await server.users.getMyInfo({ token: user3Token })
-
- const user = { displayName: 'super user 4', username: 'user4', password: 'super password' }
- const channel = { name: 'my_user_4_channel', displayName: 'my channel' }
- await server.registrations.register({ ...user, channel })
- const user4Token = await server.login.getAccessToken(user)
- const user4 = await server.users.getMyInfo({ token: user4Token })
-
- for (const user of [ user3, user4 ]) {
- expect(user.videosHistoryEnabled).to.be.false
- expect(user.videoQuota).to.equal(5242881)
- expect(user.videoQuotaDaily).to.equal(318742)
- }
- })
-
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
deleted file mode 100644
index a614d92d2..000000000
--- a/server/tests/api/server/config.ts
+++ /dev/null
@@ -1,645 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { parallelTests } from '@shared/core-utils'
-import { CustomConfig, HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
- expect(data.instance.name).to.equal('PeerTube')
- expect(data.instance.shortDescription).to.equal(
- 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
- )
- expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
-
- expect(data.instance.terms).to.equal('No terms for now.')
- expect(data.instance.creationReason).to.be.empty
- expect(data.instance.codeOfConduct).to.be.empty
- expect(data.instance.moderationInformation).to.be.empty
- expect(data.instance.administrator).to.be.empty
- expect(data.instance.maintenanceLifetime).to.be.empty
- expect(data.instance.businessModel).to.be.empty
- expect(data.instance.hardwareInformation).to.be.empty
-
- expect(data.instance.languages).to.have.lengthOf(0)
- expect(data.instance.categories).to.have.lengthOf(0)
-
- expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
- expect(data.instance.isNSFW).to.be.false
- expect(data.instance.defaultNSFWPolicy).to.equal('display')
- expect(data.instance.customizations.css).to.be.empty
- expect(data.instance.customizations.javascript).to.be.empty
-
- expect(data.services.twitter.username).to.equal('@Chocobozzz')
- expect(data.services.twitter.whitelisted).to.be.false
-
- expect(data.client.videos.miniature.preferAuthorDisplayName).to.be.false
- expect(data.client.menu.login.redirectOnSingleExternalAuth).to.be.false
-
- expect(data.cache.previews.size).to.equal(1)
- expect(data.cache.captions.size).to.equal(1)
- expect(data.cache.torrents.size).to.equal(1)
- expect(data.cache.storyboards.size).to.equal(1)
-
- expect(data.signup.enabled).to.be.true
- expect(data.signup.limit).to.equal(4)
- expect(data.signup.minimumAge).to.equal(16)
- expect(data.signup.requiresApproval).to.be.false
- expect(data.signup.requiresEmailVerification).to.be.false
-
- expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com')
- expect(data.contactForm.enabled).to.be.true
-
- expect(data.user.history.videos.enabled).to.be.true
- expect(data.user.videoQuota).to.equal(5242880)
- expect(data.user.videoQuotaDaily).to.equal(-1)
-
- expect(data.videoChannels.maxPerUser).to.equal(20)
-
- expect(data.transcoding.enabled).to.be.false
- expect(data.transcoding.remoteRunners.enabled).to.be.false
- expect(data.transcoding.allowAdditionalExtensions).to.be.false
- expect(data.transcoding.allowAudioFiles).to.be.false
- expect(data.transcoding.threads).to.equal(2)
- expect(data.transcoding.concurrency).to.equal(2)
- expect(data.transcoding.profile).to.equal('default')
- expect(data.transcoding.resolutions['144p']).to.be.false
- expect(data.transcoding.resolutions['240p']).to.be.true
- expect(data.transcoding.resolutions['360p']).to.be.true
- expect(data.transcoding.resolutions['480p']).to.be.true
- expect(data.transcoding.resolutions['720p']).to.be.true
- expect(data.transcoding.resolutions['1080p']).to.be.true
- expect(data.transcoding.resolutions['1440p']).to.be.true
- expect(data.transcoding.resolutions['2160p']).to.be.true
- expect(data.transcoding.alwaysTranscodeOriginalResolution).to.be.true
- expect(data.transcoding.webVideos.enabled).to.be.true
- expect(data.transcoding.hls.enabled).to.be.true
-
- expect(data.live.enabled).to.be.false
- expect(data.live.allowReplay).to.be.false
- expect(data.live.latencySetting.enabled).to.be.true
- expect(data.live.maxDuration).to.equal(-1)
- expect(data.live.maxInstanceLives).to.equal(20)
- expect(data.live.maxUserLives).to.equal(3)
- expect(data.live.transcoding.enabled).to.be.false
- expect(data.live.transcoding.remoteRunners.enabled).to.be.false
- expect(data.live.transcoding.threads).to.equal(2)
- expect(data.live.transcoding.profile).to.equal('default')
- expect(data.live.transcoding.resolutions['144p']).to.be.false
- expect(data.live.transcoding.resolutions['240p']).to.be.false
- expect(data.live.transcoding.resolutions['360p']).to.be.false
- expect(data.live.transcoding.resolutions['480p']).to.be.false
- expect(data.live.transcoding.resolutions['720p']).to.be.false
- expect(data.live.transcoding.resolutions['1080p']).to.be.false
- expect(data.live.transcoding.resolutions['1440p']).to.be.false
- expect(data.live.transcoding.resolutions['2160p']).to.be.false
- expect(data.live.transcoding.alwaysTranscodeOriginalResolution).to.be.true
-
- expect(data.videoStudio.enabled).to.be.false
- expect(data.videoStudio.remoteRunners.enabled).to.be.false
-
- expect(data.videoFile.update.enabled).to.be.false
-
- expect(data.import.videos.concurrency).to.equal(2)
- expect(data.import.videos.http.enabled).to.be.true
- expect(data.import.videos.torrent.enabled).to.be.true
- expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false
-
- expect(data.followers.instance.enabled).to.be.true
- expect(data.followers.instance.manualApproval).to.be.false
-
- expect(data.followings.instance.autoFollowBack.enabled).to.be.false
- expect(data.followings.instance.autoFollowIndex.enabled).to.be.false
- expect(data.followings.instance.autoFollowIndex.indexUrl).to.equal('')
-
- expect(data.broadcastMessage.enabled).to.be.false
- expect(data.broadcastMessage.level).to.equal('info')
- expect(data.broadcastMessage.message).to.equal('')
- expect(data.broadcastMessage.dismissable).to.be.false
-}
-
-function checkUpdatedConfig (data: CustomConfig) {
- expect(data.instance.name).to.equal('PeerTube updated')
- expect(data.instance.shortDescription).to.equal('my short description')
- expect(data.instance.description).to.equal('my super description')
-
- expect(data.instance.terms).to.equal('my super terms')
- expect(data.instance.creationReason).to.equal('my super creation reason')
- expect(data.instance.codeOfConduct).to.equal('my super coc')
- expect(data.instance.moderationInformation).to.equal('my super moderation information')
- expect(data.instance.administrator).to.equal('Kuja')
- expect(data.instance.maintenanceLifetime).to.equal('forever')
- expect(data.instance.businessModel).to.equal('my super business model')
- expect(data.instance.hardwareInformation).to.equal('2vCore 3GB RAM')
-
- expect(data.instance.languages).to.deep.equal([ 'en', 'es' ])
- expect(data.instance.categories).to.deep.equal([ 1, 2 ])
-
- expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
- expect(data.instance.isNSFW).to.be.true
- expect(data.instance.defaultNSFWPolicy).to.equal('blur')
- expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
- expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
-
- expect(data.services.twitter.username).to.equal('@Kuja')
- expect(data.services.twitter.whitelisted).to.be.true
-
- expect(data.client.videos.miniature.preferAuthorDisplayName).to.be.true
- expect(data.client.menu.login.redirectOnSingleExternalAuth).to.be.true
-
- expect(data.cache.previews.size).to.equal(2)
- expect(data.cache.captions.size).to.equal(3)
- expect(data.cache.torrents.size).to.equal(4)
- expect(data.cache.storyboards.size).to.equal(5)
-
- expect(data.signup.enabled).to.be.false
- expect(data.signup.limit).to.equal(5)
- expect(data.signup.requiresApproval).to.be.false
- expect(data.signup.requiresEmailVerification).to.be.false
- expect(data.signup.minimumAge).to.equal(10)
-
- // We override admin email in parallel tests, so skip this exception
- if (parallelTests() === false) {
- expect(data.admin.email).to.equal('superadmin1@example.com')
- }
-
- expect(data.contactForm.enabled).to.be.false
-
- expect(data.user.history.videos.enabled).to.be.false
- expect(data.user.videoQuota).to.equal(5242881)
- expect(data.user.videoQuotaDaily).to.equal(318742)
-
- expect(data.videoChannels.maxPerUser).to.equal(24)
-
- expect(data.transcoding.enabled).to.be.true
- expect(data.transcoding.remoteRunners.enabled).to.be.true
- expect(data.transcoding.threads).to.equal(1)
- expect(data.transcoding.concurrency).to.equal(3)
- expect(data.transcoding.allowAdditionalExtensions).to.be.true
- expect(data.transcoding.allowAudioFiles).to.be.true
- expect(data.transcoding.profile).to.equal('vod_profile')
- expect(data.transcoding.resolutions['144p']).to.be.false
- expect(data.transcoding.resolutions['240p']).to.be.false
- expect(data.transcoding.resolutions['360p']).to.be.true
- expect(data.transcoding.resolutions['480p']).to.be.true
- expect(data.transcoding.resolutions['720p']).to.be.false
- expect(data.transcoding.resolutions['1080p']).to.be.false
- expect(data.transcoding.resolutions['2160p']).to.be.false
- expect(data.transcoding.alwaysTranscodeOriginalResolution).to.be.false
- expect(data.transcoding.hls.enabled).to.be.false
- expect(data.transcoding.webVideos.enabled).to.be.true
-
- expect(data.live.enabled).to.be.true
- expect(data.live.allowReplay).to.be.true
- expect(data.live.latencySetting.enabled).to.be.false
- expect(data.live.maxDuration).to.equal(5000)
- expect(data.live.maxInstanceLives).to.equal(-1)
- expect(data.live.maxUserLives).to.equal(10)
- expect(data.live.transcoding.enabled).to.be.true
- expect(data.live.transcoding.remoteRunners.enabled).to.be.true
- expect(data.live.transcoding.threads).to.equal(4)
- expect(data.live.transcoding.profile).to.equal('live_profile')
- expect(data.live.transcoding.resolutions['144p']).to.be.true
- expect(data.live.transcoding.resolutions['240p']).to.be.true
- expect(data.live.transcoding.resolutions['360p']).to.be.true
- expect(data.live.transcoding.resolutions['480p']).to.be.true
- expect(data.live.transcoding.resolutions['720p']).to.be.true
- expect(data.live.transcoding.resolutions['1080p']).to.be.true
- expect(data.live.transcoding.resolutions['2160p']).to.be.true
- expect(data.live.transcoding.alwaysTranscodeOriginalResolution).to.be.false
-
- expect(data.videoStudio.enabled).to.be.true
- expect(data.videoStudio.remoteRunners.enabled).to.be.true
-
- expect(data.videoFile.update.enabled).to.be.true
-
- expect(data.import.videos.concurrency).to.equal(4)
- expect(data.import.videos.http.enabled).to.be.false
- expect(data.import.videos.torrent.enabled).to.be.false
- expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true
-
- expect(data.followers.instance.enabled).to.be.false
- expect(data.followers.instance.manualApproval).to.be.true
-
- expect(data.followings.instance.autoFollowBack.enabled).to.be.true
- expect(data.followings.instance.autoFollowIndex.enabled).to.be.true
- expect(data.followings.instance.autoFollowIndex.indexUrl).to.equal('https://updated.example.com')
-
- expect(data.broadcastMessage.enabled).to.be.true
- expect(data.broadcastMessage.level).to.equal('error')
- expect(data.broadcastMessage.message).to.equal('super bad message')
- expect(data.broadcastMessage.dismissable).to.be.true
-}
-
-const newCustomConfig: CustomConfig = {
- instance: {
- name: 'PeerTube updated',
- shortDescription: 'my short description',
- description: 'my super description',
- terms: 'my super terms',
- codeOfConduct: 'my super coc',
-
- creationReason: 'my super creation reason',
- moderationInformation: 'my super moderation information',
- administrator: 'Kuja',
- maintenanceLifetime: 'forever',
- businessModel: 'my super business model',
- hardwareInformation: '2vCore 3GB RAM',
-
- languages: [ 'en', 'es' ],
- categories: [ 1, 2 ],
-
- isNSFW: true,
- defaultNSFWPolicy: 'blur' as 'blur',
-
- defaultClientRoute: '/videos/recently-added',
-
- customizations: {
- javascript: 'alert("coucou")',
- css: 'body { background-color: red; }'
- }
- },
- theme: {
- default: 'default'
- },
- services: {
- twitter: {
- username: '@Kuja',
- whitelisted: true
- }
- },
- client: {
- videos: {
- miniature: {
- preferAuthorDisplayName: true
- }
- },
- menu: {
- login: {
- redirectOnSingleExternalAuth: true
- }
- }
- },
- cache: {
- previews: {
- size: 2
- },
- captions: {
- size: 3
- },
- torrents: {
- size: 4
- },
- storyboards: {
- size: 5
- }
- },
- signup: {
- enabled: false,
- limit: 5,
- requiresApproval: false,
- requiresEmailVerification: false,
- minimumAge: 10
- },
- admin: {
- email: 'superadmin1@example.com'
- },
- contactForm: {
- enabled: false
- },
- user: {
- history: {
- videos: {
- enabled: false
- }
- },
- videoQuota: 5242881,
- videoQuotaDaily: 318742
- },
- videoChannels: {
- maxPerUser: 24
- },
- transcoding: {
- enabled: true,
- remoteRunners: {
- enabled: true
- },
- allowAdditionalExtensions: true,
- allowAudioFiles: true,
- threads: 1,
- concurrency: 3,
- profile: 'vod_profile',
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': false,
- '360p': true,
- '480p': true,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- alwaysTranscodeOriginalResolution: false,
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: false
- }
- },
- live: {
- enabled: true,
- allowReplay: true,
- latencySetting: {
- enabled: false
- },
- maxDuration: 5000,
- maxInstanceLives: -1,
- maxUserLives: 10,
- transcoding: {
- enabled: true,
- remoteRunners: {
- enabled: true
- },
- threads: 4,
- profile: 'live_profile',
- resolutions: {
- '144p': true,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- alwaysTranscodeOriginalResolution: false
- }
- },
- videoStudio: {
- enabled: true,
- remoteRunners: {
- enabled: true
- }
- },
- videoFile: {
- update: {
- enabled: true
- }
- },
- import: {
- videos: {
- concurrency: 4,
- http: {
- enabled: false
- },
- torrent: {
- enabled: false
- }
- },
- videoChannelSynchronization: {
- enabled: false,
- maxPerUser: 10
- }
- },
- trending: {
- videos: {
- algorithms: {
- enabled: [ 'hot', 'most-viewed', 'most-liked' ],
- default: 'hot'
- }
- }
- },
- autoBlacklist: {
- videos: {
- ofUsers: {
- enabled: true
- }
- }
- },
- followers: {
- instance: {
- enabled: false,
- manualApproval: true
- }
- },
- followings: {
- instance: {
- autoFollowBack: {
- enabled: true
- },
- autoFollowIndex: {
- enabled: true,
- indexUrl: 'https://updated.example.com'
- }
- }
- },
- broadcastMessage: {
- enabled: true,
- level: 'error',
- message: 'super bad message',
- dismissable: true
- },
- search: {
- remoteUri: {
- anonymous: true,
- users: true
- },
- searchIndex: {
- enabled: true,
- url: 'https://search.joinpeertube.org',
- disableLocalSearch: true,
- isDefaultSearch: true
- }
- }
-}
-
-describe('Test static config', function () {
- let server: PeerTubeServer = null
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, { webadmin: { configuration: { edition: { allowed: false } } } })
- await setAccessTokensToServers([ server ])
- })
-
- it('Should tell the client that edits are not allowed', async function () {
- const data = await server.config.getConfig()
-
- expect(data.webadmin.configuration.edition.allowed).to.be.false
- })
-
- it('Should error when client tries to update', async function () {
- await server.config.updateCustomConfig({ newCustomConfig, expectedStatus: 405 })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
-
-describe('Test config', function () {
- let server: PeerTubeServer = null
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- })
-
- it('Should have a correct config on a server with registration enabled', async function () {
- const data = await server.config.getConfig()
-
- expect(data.signup.allowed).to.be.true
- })
-
- it('Should have a correct config on a server with registration enabled and a users limit', async function () {
- this.timeout(5000)
-
- await Promise.all([
- server.registrations.register({ username: 'user1' }),
- server.registrations.register({ username: 'user2' }),
- server.registrations.register({ username: 'user3' })
- ])
-
- const data = await server.config.getConfig()
-
- expect(data.signup.allowed).to.be.false
- })
-
- it('Should have the correct video allowed extensions', async function () {
- const data = await server.config.getConfig()
-
- expect(data.video.file.extensions).to.have.lengthOf(3)
- expect(data.video.file.extensions).to.contain('.mp4')
- expect(data.video.file.extensions).to.contain('.webm')
- expect(data.video.file.extensions).to.contain('.ogv')
-
- await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
- await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
-
- expect(data.contactForm.enabled).to.be.true
- })
-
- it('Should get the customized configuration', async function () {
- const data = await server.config.getCustomConfig()
-
- checkInitialConfig(server, data)
- })
-
- it('Should update the customized configuration', async function () {
- await server.config.updateCustomConfig({ newCustomConfig })
-
- const data = await server.config.getCustomConfig()
- checkUpdatedConfig(data)
- })
-
- it('Should have the correct updated video allowed extensions', async function () {
- this.timeout(30000)
-
- const data = await server.config.getConfig()
-
- expect(data.video.file.extensions).to.have.length.above(4)
- expect(data.video.file.extensions).to.contain('.mp4')
- expect(data.video.file.extensions).to.contain('.webm')
- expect(data.video.file.extensions).to.contain('.ogv')
- expect(data.video.file.extensions).to.contain('.flv')
- expect(data.video.file.extensions).to.contain('.wmv')
- expect(data.video.file.extensions).to.contain('.mkv')
- expect(data.video.file.extensions).to.contain('.mp3')
- expect(data.video.file.extensions).to.contain('.ogg')
- expect(data.video.file.extensions).to.contain('.flac')
-
- await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.OK_200 })
- await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should have the configuration updated after a restart', async function () {
- this.timeout(30000)
-
- await killallServers([ server ])
-
- await server.run()
-
- const data = await server.config.getCustomConfig()
-
- checkUpdatedConfig(data)
- })
-
- it('Should fetch the about information', async function () {
- const data = await server.config.getAbout()
-
- expect(data.instance.name).to.equal('PeerTube updated')
- expect(data.instance.shortDescription).to.equal('my short description')
- expect(data.instance.description).to.equal('my super description')
- expect(data.instance.terms).to.equal('my super terms')
- expect(data.instance.codeOfConduct).to.equal('my super coc')
-
- expect(data.instance.creationReason).to.equal('my super creation reason')
- expect(data.instance.moderationInformation).to.equal('my super moderation information')
- expect(data.instance.administrator).to.equal('Kuja')
- expect(data.instance.maintenanceLifetime).to.equal('forever')
- expect(data.instance.businessModel).to.equal('my super business model')
- expect(data.instance.hardwareInformation).to.equal('2vCore 3GB RAM')
-
- expect(data.instance.languages).to.deep.equal([ 'en', 'es' ])
- expect(data.instance.categories).to.deep.equal([ 1, 2 ])
- })
-
- it('Should remove the custom configuration', async function () {
- await server.config.deleteCustomConfig()
-
- const data = await server.config.getCustomConfig()
- checkInitialConfig(server, data)
- })
-
- it('Should enable/disable security headers', async function () {
- this.timeout(25000)
-
- {
- const res = await makeGetRequest({
- url: server.url,
- path: '/api/v1/config',
- expectedStatus: 200
- })
-
- expect(res.headers['x-frame-options']).to.exist
- expect(res.headers['x-powered-by']).to.equal('PeerTube')
- }
-
- await killallServers([ server ])
-
- const config = {
- security: {
- frameguard: { enabled: false },
- powered_by_header: { enabled: false }
- }
- }
- await server.run(config)
-
- {
- const res = await makeGetRequest({
- url: server.url,
- path: '/api/v1/config',
- expectedStatus: 200
- })
-
- expect(res.headers['x-frame-options']).to.not.exist
- expect(res.headers['x-powered-by']).to.not.exist
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/contact-form.ts b/server/tests/api/server/contact-form.ts
deleted file mode 100644
index 0256cc193..000000000
--- a/server/tests/api/server/contact-form.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { MockSmtpServer } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- ContactFormCommand,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test contact form', function () {
- let server: PeerTubeServer
- const emails: object[] = []
- let command: ContactFormCommand
-
- before(async function () {
- this.timeout(30000)
-
- const port = await MockSmtpServer.Instance.collectEmails(emails)
-
- server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port))
- await setAccessTokensToServers([ server ])
-
- command = server.contactForm
- })
-
- it('Should send a contact form', async function () {
- await command.send({
- fromEmail: 'toto@example.com',
- body: 'my super message',
- subject: 'my subject',
- fromName: 'Super toto'
- })
-
- await waitJobs(server)
-
- expect(emails).to.have.lengthOf(1)
-
- const email = emails[0]
-
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['replyTo'][0]['address']).equal('toto@example.com')
- expect(email['to'][0]['address']).equal('admin' + server.internalServerNumber + '@example.com')
- expect(email['subject']).contains('my subject')
- expect(email['text']).contains('my super message')
- })
-
- it('Should not have duplicated email address in text message', async function () {
- const text = emails[0]['text'] as string
-
- const matches = text.match(/toto@example.com/g)
- expect(matches).to.have.lengthOf(1)
- })
-
- it('Should not be able to send another contact form because of the anti spam checker', async function () {
- await wait(1000)
-
- await command.send({
- fromEmail: 'toto@example.com',
- body: 'my super message',
- subject: 'my subject',
- fromName: 'Super toto'
- })
-
- await command.send({
- fromEmail: 'toto@example.com',
- body: 'my super message',
- fromName: 'Super toto',
- subject: 'my subject',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should be able to send another contact form after a while', async function () {
- await wait(1000)
-
- await command.send({
- fromEmail: 'toto@example.com',
- fromName: 'Super toto',
- subject: 'my subject',
- body: 'my super message'
- })
- })
-
- it('Should not have the manage preferences link in the email', async function () {
- const email = emails[0]
- expect(email['text']).to.not.contain('Manage your notification preferences')
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts
deleted file mode 100644
index 9141cc697..000000000
--- a/server/tests/api/server/email.ts
+++ /dev/null
@@ -1,371 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { MockSmtpServer } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test emails', function () {
- let server: PeerTubeServer
- let userId: number
- let userId2: number
- let userAccessToken: string
-
- let videoShortUUID: string
- let videoId: number
-
- let videoUserUUID: string
-
- let verificationString: string
- let verificationString2: string
-
- const emails: object[] = []
- const user = {
- username: 'user_1',
- password: 'super_password'
- }
-
- before(async function () {
- this.timeout(120000)
-
- const emailPort = await MockSmtpServer.Instance.collectEmails(emails)
- server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort))
-
- await setAccessTokensToServers([ server ])
- await server.config.enableSignup(true)
-
- {
- const created = await server.users.create({ username: user.username, password: user.password })
- userId = created.id
-
- userAccessToken = await server.login.getAccessToken(user)
- }
-
- {
- const attributes = { name: 'my super user video' }
- const { uuid } = await server.videos.upload({ token: userAccessToken, attributes })
- videoUserUUID = uuid
- }
-
- {
- const attributes = {
- name: 'my super name'
- }
- const { shortUUID, id } = await server.videos.upload({ attributes })
- videoShortUUID = shortUUID
- videoId = id
- }
- })
-
- describe('When resetting user password', function () {
-
- it('Should ask to reset the password', async function () {
- await server.users.askResetPassword({ email: 'user_1@example.com' })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(1)
-
- const email = emails[0]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains('password')
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- expect(verificationStringMatches).not.to.be.null
-
- verificationString = verificationStringMatches[1]
- expect(verificationString).to.have.length.above(2)
-
- const userIdMatches = /userId=([0-9]+)/.exec(email['text'])
- expect(userIdMatches).not.to.be.null
-
- userId = parseInt(userIdMatches[1], 10)
- expect(verificationString).to.not.be.undefined
- })
-
- it('Should not reset the password with an invalid verification string', async function () {
- await server.users.resetPassword({
- userId,
- verificationString: verificationString + 'b',
- password: 'super_password2',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should reset the password', async function () {
- await server.users.resetPassword({ userId, verificationString, password: 'super_password2' })
- })
-
- it('Should not reset the password with the same verification string', async function () {
- await server.users.resetPassword({
- userId,
- verificationString,
- password: 'super_password3',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should login with this new password', async function () {
- user.password = 'super_password2'
-
- await server.login.getAccessToken(user)
- })
- })
-
- describe('When creating a user without password', function () {
-
- it('Should send a create password email', async function () {
- await server.users.create({ username: 'create_password', password: '' })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(2)
-
- const email = emails[1]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('create_password@example.com')
- expect(email['subject']).contains('account')
- expect(email['subject']).contains('password')
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- expect(verificationStringMatches).not.to.be.null
-
- verificationString2 = verificationStringMatches[1]
- expect(verificationString2).to.have.length.above(2)
-
- const userIdMatches = /userId=([0-9]+)/.exec(email['text'])
- expect(userIdMatches).not.to.be.null
-
- userId2 = parseInt(userIdMatches[1], 10)
- })
-
- it('Should not reset the password with an invalid verification string', async function () {
- await server.users.resetPassword({
- userId: userId2,
- verificationString: verificationString2 + 'c',
- password: 'newly_created_password',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should reset the password', async function () {
- await server.users.resetPassword({
- userId: userId2,
- verificationString: verificationString2,
- password: 'newly_created_password'
- })
- })
-
- it('Should login with this new password', async function () {
- await server.login.getAccessToken({
- username: 'create_password',
- password: 'newly_created_password'
- })
- })
- })
-
- describe('When creating an abuse', function () {
-
- it('Should send the notification email', async function () {
- const reason = 'my super bad reason'
- await server.abuses.report({ token: userAccessToken, videoId, reason })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(3)
-
- const email = emails[2]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('admin' + server.internalServerNumber + '@example.com')
- expect(email['subject']).contains('abuse')
- expect(email['text']).contains(videoShortUUID)
- })
- })
-
- describe('When blocking/unblocking user', function () {
-
- it('Should send the notification email when blocking a user', async function () {
- const reason = 'my super bad reason'
- await server.users.banUser({ userId, reason })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(4)
-
- const email = emails[3]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains(' blocked')
- expect(email['text']).contains(' blocked')
- expect(email['text']).contains('bad reason')
- })
-
- it('Should send the notification email when unblocking a user', async function () {
- await server.users.unbanUser({ userId })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(5)
-
- const email = emails[4]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains(' unblocked')
- expect(email['text']).contains(' unblocked')
- })
- })
-
- describe('When blacklisting a video', function () {
- it('Should send the notification email', async function () {
- const reason = 'my super reason'
- await server.blacklist.add({ videoId: videoUserUUID, reason })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(6)
-
- const email = emails[5]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains(' blacklisted')
- expect(email['text']).contains('my super user video')
- expect(email['text']).contains('my super reason')
- })
-
- it('Should send the notification email', async function () {
- await server.blacklist.remove({ videoId: videoUserUUID })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(7)
-
- const email = emails[6]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains(' unblacklisted')
- expect(email['text']).contains('my super user video')
- })
-
- it('Should have the manage preferences link in the email', async function () {
- const email = emails[6]
- expect(email['text']).to.contain('Manage your notification preferences')
- })
- })
-
- describe('When verifying a user email', function () {
-
- it('Should ask to send the verification email', async function () {
- await server.users.askSendVerifyEmail({ email: 'user_1@example.com' })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(8)
-
- const email = emails[7]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('user_1@example.com')
- expect(email['subject']).contains('Verify')
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- expect(verificationStringMatches).not.to.be.null
-
- verificationString = verificationStringMatches[1]
- expect(verificationString).to.not.be.undefined
- expect(verificationString).to.have.length.above(2)
-
- const userIdMatches = /userId=([0-9]+)/.exec(email['text'])
- expect(userIdMatches).not.to.be.null
-
- userId = parseInt(userIdMatches[1], 10)
- })
-
- it('Should not verify the email with an invalid verification string', async function () {
- await server.users.verifyEmail({
- userId,
- verificationString: verificationString + 'b',
- isPendingEmail: false,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should verify the email', async function () {
- await server.users.verifyEmail({ userId, verificationString })
- })
- })
-
- describe('When verifying a registration email', function () {
- let registrationId: number
- let registrationIdEmail: number
-
- before(async function () {
- const { id } = await server.registrations.requestRegistration({
- username: 'request_1',
- email: 'request_1@example.com',
- registrationReason: 'tt'
- })
- registrationId = id
- })
-
- it('Should ask to send the verification email', async function () {
- await server.registrations.askSendVerifyEmail({ email: 'request_1@example.com' })
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(9)
-
- const email = emails[8]
-
- expect(email['from'][0]['name']).equal('PeerTube')
- expect(email['from'][0]['address']).equal('test-admin@127.0.0.1')
- expect(email['to'][0]['address']).equal('request_1@example.com')
- expect(email['subject']).contains('Verify')
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- expect(verificationStringMatches).not.to.be.null
-
- verificationString = verificationStringMatches[1]
- expect(verificationString).to.not.be.undefined
- expect(verificationString).to.have.length.above(2)
-
- const registrationIdMatches = /registrationId=([0-9]+)/.exec(email['text'])
- expect(registrationIdMatches).not.to.be.null
-
- registrationIdEmail = parseInt(registrationIdMatches[1], 10)
-
- expect(registrationId).to.equal(registrationIdEmail)
- })
-
- it('Should not verify the email with an invalid verification string', async function () {
- await server.registrations.verifyEmail({
- registrationId: registrationIdEmail,
- verificationString: verificationString + 'b',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should verify the email', async function () {
- await server.registrations.verifyEmail({ registrationId: registrationIdEmail, verificationString })
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/follow-constraints.ts b/server/tests/api/server/follow-constraints.ts
deleted file mode 100644
index ff5332858..000000000
--- a/server/tests/api/server/follow-constraints.ts
+++ /dev/null
@@ -1,321 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test follow constraints', function () {
- let servers: PeerTubeServer[] = []
- let video1UUID: string
- let video2UUID: string
- let userToken: string
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video server 1' } })
- video1UUID = uuid
- }
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video server 2' } })
- video2UUID = uuid
- }
-
- const user = {
- username: 'user1',
- password: 'super_password'
- }
- await servers[0].users.create({ username: user.username, password: user.password })
- userToken = await servers[0].login.getAccessToken(user)
-
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('With a followed instance', function () {
-
- describe('With an unlogged user', function () {
-
- it('Should get the local video', async function () {
- await servers[0].videos.get({ id: video1UUID })
- })
-
- it('Should get the remote video', async function () {
- await servers[0].videos.get({ id: video2UUID })
- })
-
- it('Should list local account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ handle: 'root@' + servers[0].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ handle: 'root@' + servers[1].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list local channel videos', async function () {
- const handle = 'root_channel@' + servers[0].host
- const { total, data } = await servers[0].videos.listByChannel({ handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote channel videos', async function () {
- const handle = 'root_channel@' + servers[1].host
- const { total, data } = await servers[0].videos.listByChannel({ handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
- })
-
- describe('With a logged user', function () {
- it('Should get the local video', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video1UUID })
- })
-
- it('Should get the remote video', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
-
- it('Should list local account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@' + servers[0].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@' + servers[1].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list local channel videos', async function () {
- const handle = 'root_channel@' + servers[0].host
- const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote channel videos', async function () {
- const handle = 'root_channel@' + servers[1].host
- const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
- })
- })
-
- describe('With a non followed instance', function () {
-
- before(async function () {
- this.timeout(30000)
-
- await servers[0].follows.unfollow({ target: servers[1] })
- })
-
- describe('With an unlogged user', function () {
-
- it('Should get the local video', async function () {
- await servers[0].videos.get({ id: video1UUID })
- })
-
- it('Should not get the remote video', async function () {
- const body = await servers[0].videos.get({ id: video2UUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- const error = body as unknown as PeerTubeProblemDocument
-
- const doc = 'https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/does_not_respect_follow_constraints'
- expect(error.type).to.equal(doc)
- expect(error.code).to.equal(ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS)
-
- expect(error.detail).to.equal('Cannot get this video regarding follow constraints')
- expect(error.error).to.equal(error.detail)
-
- expect(error.status).to.equal(HttpStatusCode.FORBIDDEN_403)
-
- expect(error.originUrl).to.contains(servers[1].url)
- })
-
- it('Should list local account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({
- token: null,
- handle: 'root@' + servers[0].host
- })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should not list remote account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({
- token: null,
- handle: 'root@' + servers[1].host
- })
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- })
-
- it('Should list local channel videos', async function () {
- const handle = 'root_channel@' + servers[0].host
- const { total, data } = await servers[0].videos.listByChannel({ token: null, handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should not list remote channel videos', async function () {
- const handle = 'root_channel@' + servers[1].host
- const { total, data } = await servers[0].videos.listByChannel({ token: null, handle })
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- })
- })
-
- describe('With a logged user', function () {
-
- it('Should get the local video', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video1UUID })
- })
-
- it('Should get the remote video', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
-
- it('Should list local account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@' + servers[0].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote account videos', async function () {
- const { total, data } = await servers[0].videos.listByAccount({ token: userToken, handle: 'root@' + servers[1].host })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list local channel videos', async function () {
- const handle = 'root_channel@' + servers[0].host
- const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should list remote channel videos', async function () {
- const handle = 'root_channel@' + servers[1].host
- const { total, data } = await servers[0].videos.listByChannel({ token: userToken, handle })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
- })
- })
-
- describe('When following a remote account', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].follows.follow({ handles: [ 'root@' + servers[1].host ] })
- await waitJobs(servers)
- })
-
- it('Should get the remote video with an unlogged user', async function () {
- await servers[0].videos.get({ id: video2UUID })
- })
-
- it('Should get the remote video with a logged in user', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
- })
-
- describe('When unfollowing a remote account', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].follows.unfollow({ target: 'root@' + servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not get the remote video with an unlogged user', async function () {
- const body = await servers[0].videos.get({ id: video2UUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
-
- const error = body as unknown as PeerTubeProblemDocument
- expect(error.code).to.equal(ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS)
- })
-
- it('Should get the remote video with a logged in user', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
- })
-
- describe('When following a remote channel', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].follows.follow({ handles: [ 'root_channel@' + servers[1].host ] })
- await waitJobs(servers)
- })
-
- it('Should get the remote video with an unlogged user', async function () {
- await servers[0].videos.get({ id: video2UUID })
- })
-
- it('Should get the remote video with a logged in user', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
- })
-
- describe('When unfollowing a remote channel', function () {
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].follows.unfollow({ target: 'root_channel@' + servers[1].host })
- await waitJobs(servers)
- })
-
- it('Should not get the remote video with an unlogged user', async function () {
- const body = await servers[0].videos.get({ id: video2UUID, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
-
- const error = body as unknown as PeerTubeProblemDocument
- expect(error.code).to.equal(ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS)
- })
-
- it('Should get the remote video with a logged in user', async function () {
- await servers[0].videos.getWithToken({ token: userToken, id: video2UUID })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/follows-moderation.ts b/server/tests/api/server/follows-moderation.ts
deleted file mode 100644
index d145dd9d2..000000000
--- a/server/tests/api/server/follows-moderation.ts
+++ /dev/null
@@ -1,364 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectStartWith } from '@server/tests/shared'
-import { ActorFollow, FollowState } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- FollowsCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
- const fns = [
- servers[0].follows.getFollowings.bind(servers[0].follows),
- servers[1].follows.getFollowers.bind(servers[1].follows)
- ]
-
- for (const fn of fns) {
- const body = await fn({ start: 0, count: 5, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const follow = body.data[0]
- expect(follow.state).to.equal(state)
- expect(follow.follower.url).to.equal(servers[0].url + '/accounts/peertube')
- expect(follow.following.url).to.equal(servers[1].url + '/accounts/peertube')
- }
-}
-
-async function checkFollows (options: {
- follower: PeerTubeServer
- followerState: FollowState | 'deleted'
-
- following: PeerTubeServer
- followingState: FollowState | 'deleted'
-}) {
- const { follower, followerState, followingState, following } = options
-
- const followerUrl = follower.url + '/accounts/peertube'
- const followingUrl = following.url + '/accounts/peertube'
- const finder = (d: ActorFollow) => d.follower.url === followerUrl && d.following.url === followingUrl
-
- {
- const { data } = await follower.follows.getFollowings()
- const follow = data.find(finder)
-
- if (followerState === 'deleted') {
- expect(follow).to.not.exist
- } else {
- expect(follow.state).to.equal(followerState)
- expect(follow.follower.url).to.equal(followerUrl)
- expect(follow.following.url).to.equal(followingUrl)
- }
- }
-
- {
- const { data } = await following.follows.getFollowers()
- const follow = data.find(finder)
-
- if (followingState === 'deleted') {
- expect(follow).to.not.exist
- } else {
- expect(follow.state).to.equal(followingState)
- expect(follow.follower.url).to.equal(followerUrl)
- expect(follow.following.url).to.equal(followingUrl)
- }
- }
-}
-
-async function checkNoFollowers (servers: PeerTubeServer[]) {
- const fns = [
- servers[0].follows.getFollowings.bind(servers[0].follows),
- servers[1].follows.getFollowers.bind(servers[1].follows)
- ]
-
- for (const fn of fns) {
- const body = await fn({ start: 0, count: 5, sort: 'createdAt', state: 'accepted' })
- expect(body.total).to.equal(0)
- }
-}
-
-describe('Test follows moderation', function () {
- let servers: PeerTubeServer[] = []
- let commands: FollowsCommand[]
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- commands = servers.map(s => s.follows)
- })
-
- describe('Default behaviour', function () {
-
- it('Should have server 1 following server 2', async function () {
- this.timeout(30000)
-
- await commands[0].follow({ hosts: [ servers[1].url ] })
-
- await waitJobs(servers)
- })
-
- it('Should have correct follows', async function () {
- await checkServer1And2HasFollowers(servers)
- })
-
- it('Should remove follower on server 2', async function () {
- await commands[1].removeFollower({ follower: servers[0] })
-
- await waitJobs(servers)
- })
-
- it('Should not not have follows anymore', async function () {
- await checkNoFollowers(servers)
- })
- })
-
- describe('Disabled/Enabled followers', function () {
-
- it('Should disable followers on server 2', async function () {
- const subConfig = {
- followers: {
- instance: {
- enabled: false,
- manualApproval: false
- }
- }
- }
-
- await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
-
- await commands[0].follow({ hosts: [ servers[1].url ] })
- await waitJobs(servers)
-
- await checkNoFollowers(servers)
- })
-
- it('Should re enable followers on server 2', async function () {
- const subConfig = {
- followers: {
- instance: {
- enabled: true,
- manualApproval: false
- }
- }
- }
-
- await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
-
- await commands[0].follow({ hosts: [ servers[1].url ] })
- await waitJobs(servers)
-
- await checkServer1And2HasFollowers(servers)
- })
- })
-
- describe('Manual approbation', function () {
-
- it('Should manually approve followers', async function () {
- this.timeout(20000)
-
- await commands[0].unfollow({ target: servers[1] })
- await waitJobs(servers)
-
- const subConfig = {
- followers: {
- instance: {
- enabled: true,
- manualApproval: true
- }
- }
- }
-
- await servers[1].config.updateCustomSubConfig({ newConfig: subConfig })
- await servers[2].config.updateCustomSubConfig({ newConfig: subConfig })
-
- await commands[0].follow({ hosts: [ servers[1].url ] })
- await waitJobs(servers)
-
- await checkServer1And2HasFollowers(servers, 'pending')
- })
-
- it('Should accept a follower', async function () {
- await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
- await waitJobs(servers)
-
- await checkServer1And2HasFollowers(servers)
- })
-
- it('Should reject another follower', async function () {
- this.timeout(20000)
-
- await commands[0].follow({ hosts: [ servers[2].url ] })
- await waitJobs(servers)
-
- {
- const body = await commands[0].getFollowings()
- expect(body.total).to.equal(2)
- }
-
- {
- const body = await commands[1].getFollowers()
- expect(body.total).to.equal(1)
- }
-
- {
- const body = await commands[2].getFollowers()
- expect(body.total).to.equal(1)
- }
-
- await commands[2].rejectFollower({ follower: 'peertube@' + servers[0].host })
- await waitJobs(servers)
-
- { // server 1
- {
- const { data } = await commands[0].getFollowings({ state: 'accepted' })
- expect(data).to.have.lengthOf(1)
- }
-
- {
- const { data } = await commands[0].getFollowings({ state: 'rejected' })
- expect(data).to.have.lengthOf(1)
- expectStartWith(data[0].following.url, servers[2].url)
- }
- }
-
- { // server 3
- {
- const { data } = await commands[2].getFollowers({ state: 'accepted' })
- expect(data).to.have.lengthOf(0)
- }
-
- {
- const { data } = await commands[2].getFollowers({ state: 'rejected' })
- expect(data).to.have.lengthOf(1)
- expectStartWith(data[0].follower.url, servers[0].url)
- }
- }
- })
-
- it('Should still auto accept channel followers', async function () {
- await commands[0].follow({ handles: [ 'root_channel@' + servers[1].host ] })
-
- await waitJobs(servers)
-
- const body = await commands[0].getFollowings()
- const follow = body.data[0]
- expect(follow.following.name).to.equal('root_channel')
- expect(follow.state).to.equal('accepted')
- })
- })
-
- describe('Accept/reject state', function () {
-
- it('Should not change the follow on refollow with and without auto accept', async function () {
- const run = async () => {
- await commands[0].follow({ hosts: [ servers[2].url ] })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'rejected',
- following: servers[2],
- followingState: 'rejected'
- })
- }
-
- await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: false } } } })
- await run()
-
- await servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: true } } } })
- await run()
- })
-
- it('Should not change the rejected status on unfollow', async function () {
- await commands[0].unfollow({ target: servers[2] })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'deleted',
- following: servers[2],
- followingState: 'rejected'
- })
- })
-
- it('Should delete the follower and add again the follower', async function () {
- await commands[2].removeFollower({ follower: servers[0] })
- await waitJobs(servers)
-
- await commands[0].follow({ hosts: [ servers[2].url ] })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'pending',
- following: servers[2],
- followingState: 'pending'
- })
- })
-
- it('Should be able to reject a previously accepted follower', async function () {
- await commands[1].rejectFollower({ follower: 'peertube@' + servers[0].host })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'rejected',
- following: servers[1],
- followingState: 'rejected'
- })
- })
-
- it('Should be able to re accept a previously rejected follower', async function () {
- await commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'accepted',
- following: servers[1],
- followingState: 'accepted'
- })
- })
- })
-
- describe('Muted servers', function () {
-
- it('Should ignore follow requests of muted servers', async function () {
- await servers[1].blocklist.addToServerBlocklist({ server: servers[0].host })
-
- await commands[0].unfollow({ target: servers[1] })
-
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'deleted',
- following: servers[1],
- followingState: 'deleted'
- })
-
- await commands[0].follow({ hosts: [ servers[1].host ] })
- await waitJobs(servers)
-
- await checkFollows({
- follower: servers[0],
- followerState: 'rejected',
- following: servers[1],
- followingState: 'deleted'
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts
deleted file mode 100644
index e3e4605ee..000000000
--- a/server/tests/api/server/follows.ts
+++ /dev/null
@@ -1,641 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { completeVideoCheck, dateIsValid, expectAccountFollows, expectChannelsFollows, testCaptionFile } from '@server/tests/shared'
-import { Video, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands'
-
-describe('Test follows', function () {
-
- describe('Complex follow', function () {
- let servers: PeerTubeServer[] = []
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- })
-
- describe('Data propagation after follow', function () {
-
- it('Should not have followers/followings', async function () {
- for (const server of servers) {
- const bodies = await Promise.all([
- server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' }),
- server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
- ])
-
- for (const body of bodies) {
- expect(body.total).to.equal(0)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(0)
- }
- }
- })
-
- it('Should have server 1 following root account of server 2 and server 3', async function () {
- this.timeout(30000)
-
- await servers[0].follows.follow({
- hosts: [ servers[2].url ],
- handles: [ 'root@' + servers[1].host ]
- })
-
- await waitJobs(servers)
- })
-
- it('Should have 2 followings on server 1', async function () {
- const body = await servers[0].follows.getFollowings({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- let follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(1)
-
- const body2 = await servers[0].follows.getFollowings({ start: 1, count: 1, sort: 'createdAt' })
- follows = follows.concat(body2.data)
-
- const server2Follow = follows.find(f => f.following.host === servers[1].host)
- const server3Follow = follows.find(f => f.following.host === servers[2].host)
-
- expect(server2Follow).to.not.be.undefined
- expect(server2Follow.following.name).to.equal('root')
- expect(server2Follow.state).to.equal('accepted')
-
- expect(server3Follow).to.not.be.undefined
- expect(server3Follow.following.name).to.equal('peertube')
- expect(server3Follow.state).to.equal('accepted')
- })
-
- it('Should have 0 followings on server 2 and 3', async function () {
- for (const server of [ servers[1], servers[2] ]) {
- const body = await server.follows.getFollowings({ start: 0, count: 5, sort: 'createdAt' })
- expect(body.total).to.equal(0)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(0)
- }
- })
-
- it('Should have 1 followers on server 3', async function () {
- const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(1)
- expect(follows[0].follower.host).to.equal(servers[0].host)
- })
-
- it('Should have 0 followers on server 1 and 2', async function () {
- for (const server of [ servers[0], servers[1] ]) {
- const body = await server.follows.getFollowers({ start: 0, count: 5, sort: 'createdAt' })
- expect(body.total).to.equal(0)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(0)
- }
- })
-
- it('Should search/filter followings on server 1', async function () {
- const sort = 'createdAt'
- const start = 0
- const count = 1
-
- {
- const search = ':' + servers[1].port
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search })
- expect(body.total).to.equal(1)
-
- const follows = body.data
- expect(follows).to.have.lengthOf(1)
- expect(follows[0].following.host).to.equal(servers[1].host)
- }
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted' })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[0].follows.getFollowings({
- start,
- count,
- sort,
- search,
- state: 'accepted',
- actorType: 'Application'
- })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search, state: 'pending' })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- }
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'root' })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[0].follows.getFollowings({ start, count, sort, search: 'bla' })
- expect(body.total).to.equal(0)
-
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should search/filter followers on server 2', async function () {
- const start = 0
- const count = 5
- const sort = 'createdAt'
-
- {
- const search = servers[0].port + ''
-
- {
- const body = await servers[2].follows.getFollowers({ start, count, sort, search })
- expect(body.total).to.equal(1)
-
- const follows = body.data
- expect(follows).to.have.lengthOf(1)
- expect(follows[0].following.host).to.equal(servers[2].host)
- }
-
- {
- const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted' })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'accepted', actorType: 'Person' })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await servers[2].follows.getFollowers({
- start,
- count,
- sort,
- search,
- state: 'accepted',
- actorType: 'Application'
- })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[2].follows.getFollowers({ start, count, sort, search, state: 'pending' })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- }
-
- {
- const body = await servers[2].follows.getFollowers({ start, count, sort, search: 'bla' })
- expect(body.total).to.equal(0)
-
- const follows = body.data
- expect(follows).to.have.lengthOf(0)
- }
- })
-
- it('Should have the correct follows counts', async function () {
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
- await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
-
- // Server 2 and 3 does not know server 1 follow another server (there was not a refresh)
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
-
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
- })
-
- it('Should unfollow server 3 on server 1', async function () {
- this.timeout(15000)
-
- await servers[0].follows.unfollow({ target: servers[2] })
-
- await waitJobs(servers)
- })
-
- it('Should not follow server 3 on server 1 anymore', async function () {
- const body = await servers[0].follows.getFollowings({ start: 0, count: 2, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(1)
-
- expect(follows[0].following.host).to.equal(servers[1].host)
- })
-
- it('Should not have server 1 as follower on server 3 anymore', async function () {
- const body = await servers[2].follows.getFollowers({ start: 0, count: 1, sort: 'createdAt' })
- expect(body.total).to.equal(0)
-
- const follows = body.data
- expect(follows).to.be.an('array')
- expect(follows).to.have.lengthOf(0)
- })
-
- it('Should have the correct follows counts after the unfollow', async function () {
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
-
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
-
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 0 })
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 0, following: 0 })
- })
-
- it('Should upload a video on server 2 and 3 and propagate only the video of server 2', async function () {
- this.timeout(160000)
-
- await servers[1].videos.upload({ attributes: { name: 'server2' } })
- await servers[2].videos.upload({ attributes: { name: 'server3' } })
-
- await waitJobs(servers)
-
- {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('server2')
- }
-
- {
- const { total, data } = await servers[1].videos.list()
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('server2')
- }
-
- {
- const { total, data } = await servers[2].videos.list()
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('server3')
- }
- })
-
- it('Should remove account follow', async function () {
- this.timeout(15000)
-
- await servers[0].follows.unfollow({ target: 'root@' + servers[1].host })
-
- await waitJobs(servers)
- })
-
- it('Should have removed the account follow', async function () {
- await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
- await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
-
- {
- const { total, data } = await servers[0].follows.getFollowings()
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
-
- {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
- })
-
- it('Should follow a channel', async function () {
- this.timeout(15000)
-
- await servers[0].follows.follow({
- handles: [ 'root_channel@' + servers[1].host ]
- })
-
- await waitJobs(servers)
-
- await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
- await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
-
- {
- const { total, data } = await servers[0].follows.getFollowings()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- }
-
- {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- }
- })
- })
-
- describe('Should propagate data on a new server follow', function () {
- let video4: Video
-
- before(async function () {
- this.timeout(240000)
-
- const video4Attributes = {
- name: 'server3-4',
- category: 2,
- nsfw: true,
- licence: 6,
- tags: [ 'tag1', 'tag2', 'tag3' ]
- }
-
- await servers[2].videos.upload({ attributes: { name: 'server3-2' } })
- await servers[2].videos.upload({ attributes: { name: 'server3-3' } })
-
- const video4CreateResult = await servers[2].videos.upload({ attributes: video4Attributes })
-
- await servers[2].videos.upload({ attributes: { name: 'server3-5' } })
- await servers[2].videos.upload({ attributes: { name: 'server3-6' } })
-
- {
- const userAccessToken = await servers[2].users.generateUserAndToken('captain')
-
- await servers[2].videos.rate({ id: video4CreateResult.id, rating: 'like' })
- await servers[2].videos.rate({ token: userAccessToken, id: video4CreateResult.id, rating: 'dislike' })
- }
-
- {
- await servers[2].comments.createThread({ videoId: video4CreateResult.id, text: 'my super first comment' })
-
- await servers[2].comments.addReplyToLastThread({ text: 'my super answer to thread 1' })
- await servers[2].comments.addReplyToLastReply({ text: 'my super answer to answer of thread 1' })
- await servers[2].comments.addReplyToLastThread({ text: 'my second answer to thread 1' })
- }
-
- {
- const { id: threadId } = await servers[2].comments.createThread({ videoId: video4CreateResult.id, text: 'will be deleted' })
- await servers[2].comments.addReplyToLastThread({ text: 'answer to deleted' })
-
- const { id: replyId } = await servers[2].comments.addReplyToLastThread({ text: 'will also be deleted' })
-
- await servers[2].comments.addReplyToLastReply({ text: 'my second answer to deleted' })
-
- await servers[2].comments.delete({ videoId: video4CreateResult.id, commentId: threadId })
- await servers[2].comments.delete({ videoId: video4CreateResult.id, commentId: replyId })
- }
-
- await servers[2].captions.add({
- language: 'ar',
- videoId: video4CreateResult.id,
- fixture: 'subtitle-good2.vtt'
- })
-
- await waitJobs(servers)
-
- // Server 1 follows server 3
- await servers[0].follows.follow({ hosts: [ servers[2].url ] })
-
- await waitJobs(servers)
- })
-
- it('Should have the correct follows counts', async function () {
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[0].host, followers: 0, following: 2 })
- await expectAccountFollows({ server: servers[0], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
- await expectChannelsFollows({ server: servers[0], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
- await expectAccountFollows({ server: servers[0], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
-
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[1], handle: 'peertube@' + servers[1].host, followers: 0, following: 0 })
- await expectAccountFollows({ server: servers[1], handle: 'root@' + servers[1].host, followers: 0, following: 0 })
- await expectChannelsFollows({ server: servers[1], handle: 'root_channel@' + servers[1].host, followers: 1, following: 0 })
-
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[0].host, followers: 0, following: 1 })
- await expectAccountFollows({ server: servers[2], handle: 'peertube@' + servers[2].host, followers: 1, following: 0 })
- })
-
- it('Should have propagated videos', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(7)
-
- const video2 = data.find(v => v.name === 'server3-2')
- video4 = data.find(v => v.name === 'server3-4')
- const video6 = data.find(v => v.name === 'server3-6')
-
- expect(video2).to.not.be.undefined
- expect(video4).to.not.be.undefined
- expect(video6).to.not.be.undefined
-
- const isLocal = false
- const checkAttributes = {
- name: 'server3-4',
- category: 2,
- licence: 6,
- language: 'zh',
- nsfw: true,
- description: 'my super description',
- support: 'my super support text',
- account: {
- name: 'root',
- host: servers[2].host
- },
- isLocal,
- commentsEnabled: true,
- downloadEnabled: true,
- duration: 5,
- tags: [ 'tag1', 'tag2', 'tag3' ],
- privacy: VideoPrivacy.PUBLIC,
- likes: 1,
- dislikes: 1,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal
- },
- fixture: 'video_short.webm',
- files: [
- {
- resolution: 720,
- size: 218910
- }
- ]
- }
- await completeVideoCheck({
- server: servers[0],
- originServer: servers[2],
- videoUUID: video4.uuid,
- attributes: checkAttributes
- })
- })
-
- it('Should have propagated comments', async function () {
- const { total, data } = await servers[0].comments.listThreads({ videoId: video4.id, sort: 'createdAt' })
-
- expect(total).to.equal(2)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(2)
-
- {
- const comment = data[0]
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.text).equal('my super first comment')
- expect(comment.videoId).to.equal(video4.id)
- expect(comment.id).to.equal(comment.threadId)
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(servers[2].host)
- expect(comment.totalReplies).to.equal(3)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
-
- const threadId = comment.threadId
-
- const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId })
- expect(tree.comment.text).equal('my super first comment')
- expect(tree.children).to.have.lengthOf(2)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('my super answer to thread 1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
- expect(childOfFirstChild.children).to.have.lengthOf(0)
-
- const secondChild = tree.children[1]
- expect(secondChild.comment.text).to.equal('my second answer to thread 1')
- expect(secondChild.children).to.have.lengthOf(0)
- }
-
- {
- const deletedComment = data[1]
- expect(deletedComment).to.not.be.undefined
- expect(deletedComment.isDeleted).to.be.true
- expect(deletedComment.deletedAt).to.not.be.null
- expect(deletedComment.text).to.equal('')
- expect(deletedComment.inReplyToCommentId).to.be.null
- expect(deletedComment.account).to.be.null
- expect(deletedComment.totalReplies).to.equal(2)
- expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
-
- const tree = await servers[0].comments.getThread({ videoId: video4.id, threadId: deletedComment.threadId })
- const [ commentRoot, deletedChildRoot ] = tree.children
-
- expect(deletedChildRoot).to.not.be.undefined
- expect(deletedChildRoot.comment.isDeleted).to.be.true
- expect(deletedChildRoot.comment.deletedAt).to.not.be.null
- expect(deletedChildRoot.comment.text).to.equal('')
- expect(deletedChildRoot.comment.inReplyToCommentId).to.equal(deletedComment.id)
- expect(deletedChildRoot.comment.account).to.be.null
- expect(deletedChildRoot.children).to.have.lengthOf(1)
-
- const answerToDeletedChild = deletedChildRoot.children[0]
- expect(answerToDeletedChild.comment).to.not.be.undefined
- expect(answerToDeletedChild.comment.inReplyToCommentId).to.equal(deletedChildRoot.comment.id)
- expect(answerToDeletedChild.comment.text).to.equal('my second answer to deleted')
- expect(answerToDeletedChild.comment.account.name).to.equal('root')
-
- expect(commentRoot.comment).to.not.be.undefined
- expect(commentRoot.comment.inReplyToCommentId).to.equal(deletedComment.id)
- expect(commentRoot.comment.text).to.equal('answer to deleted')
- expect(commentRoot.comment.account.name).to.equal('root')
- }
- })
-
- it('Should have propagated captions', async function () {
- const body = await servers[0].captions.list({ videoId: video4.id })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const caption1 = body.data[0]
- expect(caption1.language.id).to.equal('ar')
- expect(caption1.language.label).to.equal('Arabic')
- expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/.+-ar.vtt$'))
- await testCaptionFile(servers[0].url, caption1.captionPath, 'Subtitle good 2.')
- })
-
- it('Should unfollow server 3 on server 1 and does not list server 3 videos', async function () {
- this.timeout(5000)
-
- await servers[0].follows.unfollow({ target: servers[2] })
-
- await waitJobs(servers)
-
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(1)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-
- describe('Simple data propagation propagate data on a new channel follow', function () {
- let servers: PeerTubeServer[] = []
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
- await setAccessTokensToServers(servers)
-
- await servers[0].videos.upload({ attributes: { name: 'video to add' } })
-
- await waitJobs(servers)
-
- for (const server of [ servers[1], servers[2] ]) {
- const video = await server.videos.find({ name: 'video to add' })
- expect(video).to.not.exist
- }
- })
-
- it('Should have propagated video after new channel follow', async function () {
- this.timeout(60000)
-
- await servers[1].follows.follow({ handles: [ 'root_channel@' + servers[0].host ] })
-
- await waitJobs(servers)
-
- const video = await servers[1].videos.find({ name: 'video to add' })
- expect(video).to.exist
- })
-
- it('Should have propagated video after new account follow', async function () {
- this.timeout(60000)
-
- await servers[2].follows.follow({ handles: [ 'root@' + servers[0].host ] })
-
- await waitJobs(servers)
-
- const video = await servers[2].videos.find({ name: 'video to add' })
- expect(video).to.exist
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
-})
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
deleted file mode 100644
index 1d524aa93..000000000
--- a/server/tests/api/server/handle-down.ts
+++ /dev/null
@@ -1,338 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { completeVideoCheck, SQLCommand } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, JobState, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- CommentsCommand,
- createMultipleServers,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test handle downs', function () {
- let servers: PeerTubeServer[] = []
- let sqlCommands: SQLCommand[] = []
-
- let threadIdServer1: number
- let threadIdServer2: number
- let commentIdServer1: number
- let commentIdServer2: number
- let missedVideo1: VideoCreateResult
- let missedVideo2: VideoCreateResult
- let unlistedVideo: VideoCreateResult
-
- const videoIdsServer1: string[] = []
-
- const videoAttributes = {
- name: 'my super name for server 1',
- category: 5,
- licence: 4,
- language: 'ja',
- nsfw: true,
- privacy: VideoPrivacy.PUBLIC,
- description: 'my super description for server 1',
- support: 'my super support text for server 1',
- tags: [ 'tag1p1', 'tag2p1' ],
- fixture: 'video_short1.webm'
- }
-
- const unlistedVideoAttributes = { ...videoAttributes, privacy: VideoPrivacy.UNLISTED }
-
- let checkAttributes: any
- let unlistedCheckAttributes: any
-
- let commentCommands: CommentsCommand[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
- commentCommands = servers.map(s => s.comments)
-
- checkAttributes = {
- name: 'my super name for server 1',
- category: 5,
- licence: 4,
- language: 'ja',
- nsfw: true,
- description: 'my super description for server 1',
- support: 'my super support text for server 1',
- account: {
- name: 'root',
- host: servers[0].host
- },
- isLocal: false,
- duration: 10,
- tags: [ 'tag1p1', 'tag2p1' ],
- privacy: VideoPrivacy.PUBLIC,
- commentsEnabled: true,
- downloadEnabled: true,
- channel: {
- name: 'root_channel',
- displayName: 'Main root channel',
- description: '',
- isLocal: false
- },
- fixture: 'video_short1.webm',
- files: [
- {
- resolution: 720,
- size: 572456
- }
- ]
- }
- unlistedCheckAttributes = { ...checkAttributes, privacy: VideoPrivacy.UNLISTED }
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- sqlCommands = servers.map(s => new SQLCommand(s))
- })
-
- it('Should remove followers that are often down', async function () {
- this.timeout(240000)
-
- // Server 2 and 3 follow server 1
- await servers[1].follows.follow({ hosts: [ servers[0].url ] })
- await servers[2].follows.follow({ hosts: [ servers[0].url ] })
-
- await waitJobs(servers)
-
- // Upload a video to server 1
- await servers[0].videos.upload({ attributes: videoAttributes })
-
- await waitJobs(servers)
-
- // And check all servers have this video
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
- }
-
- // Kill server 2
- await killallServers([ servers[1] ])
-
- // Remove server 2 follower
- for (let i = 0; i < 10; i++) {
- await servers[0].videos.upload({ attributes: videoAttributes })
- }
-
- await waitJobs([ servers[0], servers[2] ])
-
- // Kill server 3
- await killallServers([ servers[2] ])
-
- missedVideo1 = await servers[0].videos.upload({ attributes: videoAttributes })
-
- missedVideo2 = await servers[0].videos.upload({ attributes: videoAttributes })
-
- // Unlisted video
- unlistedVideo = await servers[0].videos.upload({ attributes: unlistedVideoAttributes })
-
- // Add comments to video 2
- {
- const text = 'thread 1'
- let comment = await commentCommands[0].createThread({ videoId: missedVideo2.uuid, text })
- threadIdServer1 = comment.id
-
- comment = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-1' })
-
- const created = await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: comment.id, text: 'comment 1-2' })
- commentIdServer1 = created.id
- }
-
- await waitJobs(servers[0])
- // Wait scheduler
- await wait(11000)
-
- // Only server 3 is still a follower of server 1
- const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].follower.host).to.equal(servers[2].host)
- })
-
- it('Should not have pending/processing jobs anymore', async function () {
- const states: JobState[] = [ 'waiting', 'active' ]
-
- for (const state of states) {
- const body = await servers[0].jobs.list({
- state,
- start: 0,
- count: 50,
- sort: '-createdAt'
- })
- expect(body.data).to.have.length(0)
- }
- })
-
- it('Should re-follow server 1', async function () {
- this.timeout(70000)
-
- await servers[1].run()
- await servers[2].run()
-
- await servers[1].follows.unfollow({ target: servers[0] })
- await waitJobs(servers)
-
- await servers[1].follows.follow({ hosts: [ servers[0].url ] })
-
- await waitJobs(servers)
-
- const body = await servers[0].follows.getFollowers({ start: 0, count: 2, sort: 'createdAt' })
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
- })
-
- it('Should send an update to server 3, and automatically fetch the video', async function () {
- this.timeout(15000)
-
- {
- const { data } = await servers[2].videos.list()
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(11)
- }
-
- await servers[0].videos.update({ id: missedVideo1.uuid })
- await servers[0].videos.update({ id: unlistedVideo.uuid })
-
- await waitJobs(servers)
-
- {
- const { data } = await servers[2].videos.list()
- expect(data).to.be.an('array')
- // 1 video is unlisted
- expect(data).to.have.lengthOf(12)
- }
-
- // Check unlisted video
- const video = await servers[2].videos.get({ id: unlistedVideo.uuid })
- await completeVideoCheck({ server: servers[2], originServer: servers[0], videoUUID: video.uuid, attributes: unlistedCheckAttributes })
- })
-
- it('Should send comments on a video to server 3, and automatically fetch the video', async function () {
- this.timeout(25000)
-
- await commentCommands[0].addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer1, text: 'comment 1-3' })
-
- await waitJobs(servers)
-
- await servers[2].videos.get({ id: missedVideo2.uuid })
-
- {
- const { data } = await servers[2].comments.listThreads({ videoId: missedVideo2.uuid })
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
-
- threadIdServer2 = data[0].id
-
- const tree = await servers[2].comments.getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer2 })
- expect(tree.comment.text).equal('thread 1')
- expect(tree.children).to.have.lengthOf(1)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('comment 1-1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
- expect(childOfFirstChild.children).to.have.lengthOf(1)
-
- const childOfChildFirstChild = childOfFirstChild.children[0]
- expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
- expect(childOfChildFirstChild.children).to.have.lengthOf(0)
-
- commentIdServer2 = childOfChildFirstChild.comment.id
- }
- })
-
- it('Should correctly reply to the comment', async function () {
- this.timeout(15000)
-
- await servers[2].comments.addReply({ videoId: missedVideo2.uuid, toCommentId: commentIdServer2, text: 'comment 1-4' })
-
- await waitJobs(servers)
-
- const tree = await commentCommands[0].getThread({ videoId: missedVideo2.uuid, threadId: threadIdServer1 })
-
- expect(tree.comment.text).equal('thread 1')
- expect(tree.children).to.have.lengthOf(1)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('comment 1-1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('comment 1-2')
- expect(childOfFirstChild.children).to.have.lengthOf(1)
-
- const childOfChildFirstChild = childOfFirstChild.children[0]
- expect(childOfChildFirstChild.comment.text).to.equal('comment 1-3')
- expect(childOfChildFirstChild.children).to.have.lengthOf(1)
-
- const childOfChildOfChildOfFirstChild = childOfChildFirstChild.children[0]
- expect(childOfChildOfChildOfFirstChild.comment.text).to.equal('comment 1-4')
- expect(childOfChildOfChildOfFirstChild.children).to.have.lengthOf(0)
- })
-
- it('Should upload many videos on server 1', async function () {
- this.timeout(240000)
-
- for (let i = 0; i < 10; i++) {
- const uuid = (await servers[0].videos.quickUpload({ name: 'video ' + i })).uuid
- videoIdsServer1.push(uuid)
- }
-
- await waitJobs(servers)
-
- for (const id of videoIdsServer1) {
- await servers[1].videos.get({ id })
- }
-
- await waitJobs(servers)
- await sqlCommands[1].setActorFollowScores(20)
-
- // Wait video expiration
- await wait(11000)
-
- // Refresh video -> score + 10 = 30
- await servers[1].videos.get({ id: videoIdsServer1[0] })
-
- await waitJobs(servers)
- })
-
- it('Should remove followings that are down', async function () {
- this.timeout(120000)
-
- await killallServers([ servers[0] ])
-
- // Wait video expiration
- await wait(11000)
-
- for (let i = 0; i < 5; i++) {
- try {
- await servers[1].videos.get({ id: videoIdsServer1[i] })
- await waitJobs([ servers[1] ])
- await wait(1500)
- } catch {}
- }
-
- for (const id of videoIdsServer1) {
- await servers[1].videos.get({ id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- }
- })
-
- after(async function () {
- for (const sqlCommand of sqlCommands) {
- await sqlCommand.cleanup()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/homepage.ts b/server/tests/api/server/homepage.ts
deleted file mode 100644
index 9c45800f2..000000000
--- a/server/tests/api/server/homepage.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- CustomPagesCommand,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar
-} from '../../../../shared/server-commands/index'
-
-async function getHomepageState (server: PeerTubeServer) {
- const config = await server.config.getConfig()
-
- return config.homepage.enabled
-}
-
-describe('Test instance homepage actions', function () {
- let server: PeerTubeServer
- let command: CustomPagesCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(server)
-
- command = server.customPage
- })
-
- it('Should not have a homepage', async function () {
- const state = await getHomepageState(server)
- expect(state).to.be.false
-
- await command.getInstanceHomepage({ expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should set a homepage', async function () {
- await command.updateInstanceHomepage({ content: '' })
-
- const page = await command.getInstanceHomepage()
- expect(page.content).to.equal('')
-
- const state = await getHomepageState(server)
- expect(state).to.be.true
- })
-
- it('Should have the same homepage after a restart', async function () {
- this.timeout(30000)
-
- await killallServers([ server ])
-
- await server.run()
-
- const page = await command.getInstanceHomepage()
- expect(page.content).to.equal('')
-
- const state = await getHomepageState(server)
- expect(state).to.be.true
- })
-
- it('Should empty the homepage', async function () {
- await command.updateInstanceHomepage({ content: '' })
-
- const page = await command.getInstanceHomepage()
- expect(page.content).to.be.empty
-
- const state = await getHomepageState(server)
- expect(state).to.be.false
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts
deleted file mode 100644
index 78522c246..000000000
--- a/server/tests/api/server/index.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import './auto-follows'
-import './bulk'
-import './config-defaults'
-import './config'
-import './contact-form'
-import './email'
-import './follow-constraints'
-import './follows'
-import './follows-moderation'
-import './homepage'
-import './handle-down'
-import './jobs'
-import './logs'
-import './reverse-proxy'
-import './services'
-import './slow-follows'
-import './stats'
-import './tracker'
-import './no-client'
-import './open-telemetry'
-import './plugins'
-import './proxy'
diff --git a/server/tests/api/server/jobs.ts b/server/tests/api/server/jobs.ts
deleted file mode 100644
index d0e6df719..000000000
--- a/server/tests/api/server/jobs.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { dateIsValid } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test jobs', function () {
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should create some jobs', async function () {
- this.timeout(240000)
-
- await servers[1].videos.upload({ attributes: { name: 'video1' } })
- await servers[1].videos.upload({ attributes: { name: 'video2' } })
-
- await waitJobs(servers)
- })
-
- it('Should list jobs', async function () {
- const body = await servers[1].jobs.list({ state: 'completed' })
- expect(body.total).to.be.above(2)
- expect(body.data).to.have.length.above(2)
- })
-
- it('Should list jobs with sort, pagination and job type', async function () {
- {
- const body = await servers[1].jobs.list({
- state: 'completed',
- start: 1,
- count: 2,
- sort: 'createdAt'
- })
- expect(body.total).to.be.above(2)
- expect(body.data).to.have.lengthOf(2)
-
- let job = body.data[0]
- // Skip repeat jobs
- if (job.type === 'videos-views-stats') job = body.data[1]
-
- expect(job.state).to.equal('completed')
- expect(dateIsValid(job.createdAt as string)).to.be.true
- expect(dateIsValid(job.processedOn as string)).to.be.true
- expect(dateIsValid(job.finishedOn as string)).to.be.true
- }
-
- {
- const body = await servers[1].jobs.list({
- state: 'completed',
- start: 0,
- count: 100,
- sort: 'createdAt',
- jobType: 'activitypub-http-broadcast'
- })
- expect(body.total).to.be.above(2)
-
- for (const j of body.data) {
- expect(j.type).to.equal('activitypub-http-broadcast')
- }
- }
- })
-
- it('Should list all jobs', async function () {
- const body = await servers[1].jobs.list()
- expect(body.total).to.be.above(2)
-
- const jobs = body.data
- expect(jobs).to.have.length.above(2)
-
- expect(jobs.find(j => j.state === 'completed')).to.not.be.undefined
- })
-
- it('Should pause the job queue', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video2' } })
- await waitJobs(servers)
-
- await servers[1].jobs.pauseJobQueue()
- await servers[1].videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
-
- await wait(5000)
-
- {
- const body = await servers[1].jobs.list({ state: 'waiting', jobType: 'video-transcoding' })
- // waiting includes waiting-children
- expect(body.data).to.have.lengthOf(4)
- }
-
- {
- const body = await servers[1].jobs.list({ state: 'waiting-children', jobType: 'video-transcoding' })
- expect(body.data).to.have.lengthOf(1)
- }
- })
-
- it('Should resume the job queue', async function () {
- this.timeout(120000)
-
- await servers[1].jobs.resumeJobQueue()
-
- await waitJobs(servers)
-
- const body = await servers[1].jobs.list({ state: 'waiting', jobType: 'video-transcoding' })
- expect(body.data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/logs.ts b/server/tests/api/server/logs.ts
deleted file mode 100644
index 9cf04c501..000000000
--- a/server/tests/api/server/logs.ts
+++ /dev/null
@@ -1,265 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- LogsCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test logs', function () {
- let server: PeerTubeServer
- let logsCommand: LogsCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- logsCommand = server.logs
- })
-
- describe('With the standard log file', function () {
-
- it('Should get logs with a start date', async function () {
- this.timeout(60000)
-
- await server.videos.upload({ attributes: { name: 'video 1' } })
- await waitJobs([ server ])
-
- const now = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 2' } })
- await waitJobs([ server ])
-
- const body = await logsCommand.getLogs({ startDate: now })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('Video with name video 1')).to.be.false
- expect(logsString.includes('Video with name video 2')).to.be.true
- })
-
- it('Should get logs with an end date', async function () {
- this.timeout(60000)
-
- await server.videos.upload({ attributes: { name: 'video 3' } })
- await waitJobs([ server ])
-
- const now1 = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 4' } })
- await waitJobs([ server ])
-
- const now2 = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 5' } })
- await waitJobs([ server ])
-
- const body = await logsCommand.getLogs({ startDate: now1, endDate: now2 })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('Video with name video 3')).to.be.false
- expect(logsString.includes('Video with name video 4')).to.be.true
- expect(logsString.includes('Video with name video 5')).to.be.false
- })
-
- it('Should filter by level', async function () {
- this.timeout(60000)
-
- const now = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 6' } })
- await waitJobs([ server ])
-
- {
- const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('Video with name video 6')).to.be.true
- }
-
- {
- const body = await logsCommand.getLogs({ startDate: now, level: 'warn' })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('Video with name video 6')).to.be.false
- }
- })
-
- it('Should filter by tag', async function () {
- const now = new Date()
-
- const { uuid } = await server.videos.upload({ attributes: { name: 'video 6' } })
- await waitJobs([ server ])
-
- {
- const body = await logsCommand.getLogs({ startDate: now, level: 'debug', tagsOneOf: [ 'toto' ] })
- expect(body).to.have.lengthOf(0)
- }
-
- {
- const body = await logsCommand.getLogs({ startDate: now, level: 'debug', tagsOneOf: [ uuid ] })
- expect(body).to.not.have.lengthOf(0)
-
- for (const line of body) {
- expect(line.tags).to.contain(uuid)
- }
- }
- })
-
- it('Should log ping requests', async function () {
- const now = new Date()
-
- await server.servers.ping()
-
- const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('/api/v1/ping')).to.be.true
- })
-
- it('Should not log ping requests', async function () {
- this.timeout(60000)
-
- await killallServers([ server ])
-
- await server.run({ log: { log_ping_requests: false } })
-
- const now = new Date()
-
- await server.servers.ping()
-
- const body = await logsCommand.getLogs({ startDate: now, level: 'info' })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('/api/v1/ping')).to.be.false
- })
- })
-
- describe('With the audit log', function () {
-
- it('Should get logs with a start date', async function () {
- this.timeout(60000)
-
- await server.videos.upload({ attributes: { name: 'video 7' } })
- await waitJobs([ server ])
-
- const now = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 8' } })
- await waitJobs([ server ])
-
- const body = await logsCommand.getAuditLogs({ startDate: now })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('video 7')).to.be.false
- expect(logsString.includes('video 8')).to.be.true
-
- expect(body).to.have.lengthOf(1)
-
- const item = body[0]
-
- const message = JSON.parse(item.message)
- expect(message.domain).to.equal('videos')
- expect(message.action).to.equal('create')
- })
-
- it('Should get logs with an end date', async function () {
- this.timeout(60000)
-
- await server.videos.upload({ attributes: { name: 'video 9' } })
- await waitJobs([ server ])
-
- const now1 = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 10' } })
- await waitJobs([ server ])
-
- const now2 = new Date()
-
- await server.videos.upload({ attributes: { name: 'video 11' } })
- await waitJobs([ server ])
-
- const body = await logsCommand.getAuditLogs({ startDate: now1, endDate: now2 })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('video 9')).to.be.false
- expect(logsString.includes('video 10')).to.be.true
- expect(logsString.includes('video 11')).to.be.false
- })
- })
-
- describe('When creating log from the client', function () {
-
- it('Should create a warn client log', async function () {
- const now = new Date()
-
- await server.logs.createLogClient({
- payload: {
- level: 'warn',
- url: 'http://example.com',
- message: 'my super client message'
- },
- token: null
- })
-
- const body = await logsCommand.getLogs({ startDate: now })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('my super client message')).to.be.true
- })
-
- it('Should create an error authenticated client log', async function () {
- const now = new Date()
-
- await server.logs.createLogClient({
- payload: {
- url: 'https://example.com/page1',
- level: 'error',
- message: 'my super client message 2',
- userAgent: 'super user agent',
- meta: '{hello}',
- stackTrace: 'super stack trace'
- }
- })
-
- const body = await logsCommand.getLogs({ startDate: now })
- const logsString = JSON.stringify(body)
-
- expect(logsString.includes('my super client message 2')).to.be.true
- expect(logsString.includes('super user agent')).to.be.true
- expect(logsString.includes('super stack trace')).to.be.true
- expect(logsString.includes('{hello}')).to.be.true
- expect(logsString.includes('https://example.com/page1')).to.be.true
- })
-
- it('Should refuse to create client logs', async function () {
- await server.kill()
-
- await server.run({
- log: {
- accept_client_log: false
- }
- })
-
- await server.logs.createLogClient({
- payload: {
- level: 'warn',
- url: 'http://example.com',
- message: 'my super client message'
- },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/no-client.ts b/server/tests/api/server/no-client.ts
deleted file mode 100644
index 193f6c987..000000000
--- a/server/tests/api/server/no-client.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import request from 'supertest'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/server-commands'
-
-describe('Start and stop server without web client routes', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {}, { peertubeArgs: [ '--no-client' ] })
- })
-
- it('Should fail getting the client', function () {
- const req = request(server.url)
- .get('/')
-
- return req.expect(HttpStatusCode.NOT_FOUND_404)
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/open-telemetry.ts b/server/tests/api/server/open-telemetry.ts
deleted file mode 100644
index 508e9d649..000000000
--- a/server/tests/api/server/open-telemetry.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectLogContain, expectLogDoesNotContain, MockHTTP } from '@server/tests/shared'
-import { HttpStatusCode, PlaybackMetricCreate, VideoPrivacy, VideoResolution } from '@shared/models'
-import { cleanupTests, createSingleServer, makeRawRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Open Telemetry', function () {
- let server: PeerTubeServer
-
- describe('Metrics', function () {
- const metricsUrl = 'http://127.0.0.1:9092/metrics'
-
- it('Should not enable open telemetry metrics', async function () {
- this.timeout(60000)
-
- server = await createSingleServer(1)
-
- let hasError = false
- try {
- await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- } catch (err) {
- hasError = err.message.includes('ECONNREFUSED')
- }
-
- expect(hasError).to.be.true
-
- await server.kill()
- })
-
- it('Should enable open telemetry metrics', async function () {
- this.timeout(120000)
-
- await server.run({
- open_telemetry: {
- metrics: {
- enabled: true
- }
- }
- })
-
- // Simulate a HTTP request
- await server.videos.list()
-
- const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).to.contain('peertube_job_queue_total{')
- expect(res.text).to.contain('http_request_duration_ms_bucket{')
- })
-
- it('Should have playback metrics', async function () {
- await setAccessTokensToServers([ server ])
-
- const video = await server.videos.quickUpload({ name: 'video' })
-
- await server.metrics.addPlaybackMetric({
- metrics: {
- playerMode: 'p2p-media-loader',
- resolution: VideoResolution.H_1080P,
- fps: 30,
- resolutionChanges: 1,
- errors: 2,
- downloadedBytesP2P: 0,
- downloadedBytesHTTP: 0,
- uploadedBytesP2P: 5,
- p2pPeers: 1,
- p2pEnabled: false,
- videoId: video.uuid
- }
- })
-
- const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- expect(res.text).to.contain('peertube_playback_http_downloaded_bytes_total{')
- expect(res.text).to.contain('peertube_playback_p2p_peers{')
- expect(res.text).to.contain('p2pEnabled="false"')
- })
-
- it('Should take the last playback metric', async function () {
- await setAccessTokensToServers([ server ])
-
- const video = await server.videos.quickUpload({ name: 'video' })
-
- const metrics = {
- playerMode: 'p2p-media-loader',
- resolution: VideoResolution.H_1080P,
- fps: 30,
- resolutionChanges: 1,
- errors: 2,
- downloadedBytesP2P: 0,
- downloadedBytesHTTP: 0,
- uploadedBytesP2P: 5,
- p2pPeers: 7,
- p2pEnabled: false,
- videoId: video.uuid
- } as PlaybackMetricCreate
-
- await server.metrics.addPlaybackMetric({ metrics })
-
- metrics.p2pPeers = 42
- await server.metrics.addPlaybackMetric({ metrics })
-
- const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- // eslint-disable-next-line max-len
- const label = `{videoOrigin="local",playerMode="p2p-media-loader",resolution="1080",fps="30",p2pEnabled="false",videoUUID="${video.uuid}"}`
- expect(res.text).to.contain(`peertube_playback_p2p_peers${label} 42`)
- expect(res.text).to.not.contain(`peertube_playback_p2p_peers${label} 7`)
- })
-
- it('Should disable http request duration metrics', async function () {
- await server.kill()
-
- await server.run({
- open_telemetry: {
- metrics: {
- enabled: true,
- http_request_duration: {
- enabled: false
- }
- }
- }
- })
-
- // Simulate a HTTP request
- await server.videos.list()
-
- const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).to.not.contain('http_request_duration_ms_bucket{')
- })
-
- after(async function () {
- await server.kill()
- })
- })
-
- describe('Tracing', function () {
- let mockHTTP: MockHTTP
- let mockPort: number
-
- before(async function () {
- mockHTTP = new MockHTTP()
- mockPort = await mockHTTP.initialize()
- })
-
- it('Should enable open telemetry tracing', async function () {
- server = await createSingleServer(1)
-
- await expectLogDoesNotContain(server, 'Registering Open Telemetry tracing')
-
- await server.kill()
- })
-
- it('Should enable open telemetry metrics', async function () {
- await server.run({
- open_telemetry: {
- tracing: {
- enabled: true,
- jaeger_exporter: {
- endpoint: 'http://127.0.0.1:' + mockPort
- }
- }
- }
- })
-
- await expectLogContain(server, 'Registering Open Telemetry tracing')
- })
-
- it('Should upload a video and correctly works', async function () {
- await setAccessTokensToServers([ server ])
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PUBLIC })
-
- const video = await server.videos.get({ id: uuid })
-
- expect(video.name).to.equal('video')
- })
-
- after(async function () {
- await mockHTTP.terminate()
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts
deleted file mode 100644
index a0e9db1d3..000000000
--- a/server/tests/api/server/plugins.ts
+++ /dev/null
@@ -1,409 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, remove } from 'fs-extra'
-import { join } from 'path'
-import { SQLCommand, testHelloWorldRegisteredSettings } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, PluginType } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- makeGetRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test plugins', function () {
- let server: PeerTubeServer
- let sqlCommand: SQLCommand
- let command: PluginsCommand
-
- before(async function () {
- this.timeout(30000)
-
- const configOverride = {
- plugins: {
- index: { check_latest_versions_interval: '5 seconds' }
- }
- }
- server = await createSingleServer(1, configOverride)
- await setAccessTokensToServers([ server ])
-
- command = server.plugins
-
- sqlCommand = new SQLCommand(server)
- })
-
- it('Should list and search available plugins and themes', async function () {
- this.timeout(30000)
-
- {
- const body = await command.listAvailable({
- count: 1,
- start: 0,
- pluginType: PluginType.THEME,
- search: 'background-red'
- })
-
- expect(body.total).to.be.at.least(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body1 = await command.listAvailable({
- count: 2,
- start: 0,
- sort: 'npmName'
- })
- expect(body1.total).to.be.at.least(2)
-
- const data1 = body1.data
- expect(data1).to.have.lengthOf(2)
-
- const body2 = await command.listAvailable({
- count: 2,
- start: 0,
- sort: '-npmName'
- })
- expect(body2.total).to.be.at.least(2)
-
- const data2 = body2.data
- expect(data2).to.have.lengthOf(2)
-
- expect(data1[0].npmName).to.not.equal(data2[0].npmName)
- }
-
- {
- const body = await command.listAvailable({
- count: 10,
- start: 0,
- pluginType: PluginType.THEME,
- search: 'background-red',
- currentPeerTubeEngine: '1.0.0'
- })
-
- const p = body.data.find(p => p.npmName === 'peertube-theme-background-red')
- expect(p).to.be.undefined
- }
- })
-
- it('Should install a plugin and a theme', async function () {
- this.timeout(30000)
-
- await command.install({ npmName: 'peertube-plugin-hello-world' })
- await command.install({ npmName: 'peertube-theme-background-red' })
- })
-
- it('Should have the plugin loaded in the configuration', async function () {
- for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
- const theme = config.theme.registered.find(r => r.name === 'background-red')
- expect(theme).to.not.be.undefined
- expect(theme.npmName).to.equal('peertube-theme-background-red')
-
- const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
- expect(plugin).to.not.be.undefined
- expect(plugin.npmName).to.equal('peertube-plugin-hello-world')
- }
- })
-
- it('Should update the default theme in the configuration', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- theme: { default: 'background-red' }
- }
- })
-
- for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
- expect(config.theme.default).to.equal('background-red')
- }
- })
-
- it('Should update my default theme', async function () {
- await server.users.updateMe({ theme: 'background-red' })
-
- const user = await server.users.getMyInfo()
- expect(user.theme).to.equal('background-red')
- })
-
- it('Should list plugins and themes', async function () {
- {
- const body = await command.list({
- count: 1,
- start: 0,
- pluginType: PluginType.THEME
- })
- expect(body.total).to.be.at.least(1)
-
- const data = body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('background-red')
- }
-
- {
- const { data } = await command.list({
- count: 2,
- start: 0,
- sort: 'name'
- })
-
- expect(data[0].name).to.equal('background-red')
- expect(data[1].name).to.equal('hello-world')
- }
-
- {
- const body = await command.list({
- count: 2,
- start: 1,
- sort: 'name'
- })
-
- expect(body.data[0].name).to.equal('hello-world')
- }
- })
-
- it('Should get registered settings', async function () {
- await testHelloWorldRegisteredSettings(server)
- })
-
- it('Should get public settings', async function () {
- const body = await command.getPublicSettings({ npmName: 'peertube-plugin-hello-world' })
- const publicSettings = body.publicSettings
-
- expect(Object.keys(publicSettings)).to.have.lengthOf(1)
- expect(Object.keys(publicSettings)).to.deep.equal([ 'user-name' ])
- expect(publicSettings['user-name']).to.be.null
- })
-
- it('Should update the settings', async function () {
- const settings = {
- 'admin-name': 'Cid'
- }
-
- await command.updateSettings({
- npmName: 'peertube-plugin-hello-world',
- settings
- })
- })
-
- it('Should have watched settings changes', async function () {
- await server.servers.waitUntilLog('Settings changed!')
- })
-
- it('Should get a plugin and a theme', async function () {
- {
- const plugin = await command.get({ npmName: 'peertube-plugin-hello-world' })
-
- expect(plugin.type).to.equal(PluginType.PLUGIN)
- expect(plugin.name).to.equal('hello-world')
- expect(plugin.description).to.exist
- expect(plugin.homepage).to.exist
- expect(plugin.uninstalled).to.be.false
- expect(plugin.enabled).to.be.true
- expect(plugin.description).to.exist
- expect(plugin.version).to.exist
- expect(plugin.peertubeEngine).to.exist
- expect(plugin.createdAt).to.exist
-
- expect(plugin.settings).to.not.be.undefined
- expect(plugin.settings['admin-name']).to.equal('Cid')
- }
-
- {
- const plugin = await command.get({ npmName: 'peertube-theme-background-red' })
-
- expect(plugin.type).to.equal(PluginType.THEME)
- expect(plugin.name).to.equal('background-red')
- expect(plugin.description).to.exist
- expect(plugin.homepage).to.exist
- expect(plugin.uninstalled).to.be.false
- expect(plugin.enabled).to.be.true
- expect(plugin.description).to.exist
- expect(plugin.version).to.exist
- expect(plugin.peertubeEngine).to.exist
- expect(plugin.createdAt).to.exist
-
- expect(plugin.settings).to.be.null
- }
- })
-
- it('Should update the plugin and the theme', async function () {
- this.timeout(180000)
-
- // Wait the scheduler that get the latest plugins versions
- await wait(6000)
-
- async function testUpdate (type: 'plugin' | 'theme', name: string) {
- // Fake update our plugin version
- await sqlCommand.setPluginVersion(name, '0.0.1')
-
- // Fake update package.json
- const packageJSON = await command.getPackageJSON(`peertube-${type}-${name}`)
- const oldVersion = packageJSON.version
-
- packageJSON.version = '0.0.1'
- await command.updatePackageJSON(`peertube-${type}-${name}`, packageJSON)
-
- // Restart the server to take into account this change
- await killallServers([ server ])
- await server.run()
-
- const checkConfig = async (version: string) => {
- for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
- expect(config[type].registered.find(r => r.name === name).version).to.equal(version)
- }
- }
-
- const getPluginFromAPI = async () => {
- const body = await command.list({ pluginType: type === 'plugin' ? PluginType.PLUGIN : PluginType.THEME })
-
- return body.data.find(p => p.name === name)
- }
-
- {
- const plugin = await getPluginFromAPI()
- expect(plugin.version).to.equal('0.0.1')
- expect(plugin.latestVersion).to.exist
- expect(plugin.latestVersion).to.not.equal('0.0.1')
-
- await checkConfig('0.0.1')
- }
-
- {
- await command.update({ npmName: `peertube-${type}-${name}` })
-
- const plugin = await getPluginFromAPI()
- expect(plugin.version).to.equal(oldVersion)
-
- const updatedPackageJSON = await command.getPackageJSON(`peertube-${type}-${name}`)
- expect(updatedPackageJSON.version).to.equal(oldVersion)
-
- await checkConfig(oldVersion)
- }
- }
-
- await testUpdate('theme', 'background-red')
- await testUpdate('plugin', 'hello-world')
- })
-
- it('Should uninstall the plugin', async function () {
- await command.uninstall({ npmName: 'peertube-plugin-hello-world' })
-
- const body = await command.list({ pluginType: PluginType.PLUGIN })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should list uninstalled plugins', async function () {
- const body = await command.list({ pluginType: PluginType.PLUGIN, uninstalled: true })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const plugin = body.data[0]
- expect(plugin.name).to.equal('hello-world')
- expect(plugin.enabled).to.be.false
- expect(plugin.uninstalled).to.be.true
- })
-
- it('Should uninstall the theme', async function () {
- await command.uninstall({ npmName: 'peertube-theme-background-red' })
- })
-
- it('Should have updated the configuration', async function () {
- for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
- expect(config.theme.default).to.equal('default')
-
- const theme = config.theme.registered.find(r => r.name === 'background-red')
- expect(theme).to.be.undefined
-
- const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
- expect(plugin).to.be.undefined
- }
- })
-
- it('Should have updated the user theme', async function () {
- const user = await server.users.getMyInfo()
- expect(user.theme).to.equal('instance-default')
- })
-
- it('Should not install a broken plugin', async function () {
- this.timeout(60000)
-
- async function check () {
- const body = await command.list({ pluginType: PluginType.PLUGIN })
- const plugins = body.data
- expect(plugins.find(p => p.name === 'test-broken')).to.not.exist
- }
-
- await command.install({
- path: PluginsCommand.getPluginTestPath('-broken'),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await check()
-
- await killallServers([ server ])
- await server.run()
-
- await check()
- })
-
- it('Should rebuild native modules on Node ABI change', async function () {
- this.timeout(60000)
-
- const removeNativeModule = async () => {
- await remove(join(baseNativeModule, 'build'))
- await remove(join(baseNativeModule, 'prebuilds'))
- }
-
- await command.install({ path: PluginsCommand.getPluginTestPath('-native') })
-
- await makeGetRequest({
- url: server.url,
- path: '/plugins/test-native/router',
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-
- const query = `UPDATE "application" SET "nodeABIVersion" = 1`
- await sqlCommand.updateQuery(query)
-
- const baseNativeModule = server.servers.buildDirectory(join('plugins', 'node_modules', 'a-native-example'))
-
- await removeNativeModule()
- await server.kill()
- await server.run()
-
- await wait(3000)
-
- expect(await pathExists(join(baseNativeModule, 'build'))).to.be.true
- expect(await pathExists(join(baseNativeModule, 'prebuilds'))).to.be.true
-
- await makeGetRequest({
- url: server.url,
- path: '/plugins/test-native/router',
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-
- await removeNativeModule()
-
- await server.kill()
- await server.run()
-
- expect(await pathExists(join(baseNativeModule, 'build'))).to.be.false
- expect(await pathExists(join(baseNativeModule, 'prebuilds'))).to.be.false
-
- await makeGetRequest({
- url: server.url,
- path: '/plugins/test-native/router',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- after(async function () {
- await sqlCommand.cleanup()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/proxy.ts b/server/tests/api/server/proxy.ts
deleted file mode 100644
index 9337468d5..000000000
--- a/server/tests/api/server/proxy.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectNotStartWith, expectStartWith, FIXTURE_URLS, MockProxy } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test proxy', function () {
- let servers: PeerTubeServer[] = []
- let proxy: MockProxy
-
- const goodEnv = { HTTP_PROXY: '' }
- const badEnv = { HTTP_PROXY: 'http://127.0.0.1:9000' }
-
- before(async function () {
- this.timeout(120000)
-
- proxy = new MockProxy()
-
- const proxyPort = await proxy.initialize()
- servers = await createMultipleServers(2)
-
- goodEnv.HTTP_PROXY = 'http://127.0.0.1:' + proxyPort
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Federation', function () {
-
- it('Should succeed federation with the appropriate proxy config', async function () {
- this.timeout(40000)
-
- await servers[0].kill()
- await servers[0].run({}, { env: goodEnv })
-
- await servers[0].videos.quickUpload({ name: 'video 1' })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- }
- })
-
- it('Should fail federation with a wrong proxy config', async function () {
- this.timeout(40000)
-
- await servers[0].kill()
- await servers[0].run({}, { env: badEnv })
-
- await servers[0].videos.quickUpload({ name: 'video 2' })
-
- await waitJobs(servers)
-
- {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
- }
-
- {
- const { total, data } = await servers[1].videos.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- }
- })
- })
-
- describe('Videos import', async function () {
-
- function quickImport (expectedStatus: HttpStatusCode = HttpStatusCode.OK_200) {
- return servers[0].imports.importVideo({
- attributes: {
- name: 'video import',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- targetUrl: FIXTURE_URLS.peertube_long
- },
- expectedStatus
- })
- }
-
- it('Should succeed import with the appropriate proxy config', async function () {
- this.timeout(240000)
-
- await servers[0].kill()
- await servers[0].run({}, { env: goodEnv })
-
- await quickImport()
-
- await waitJobs(servers)
-
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
- })
-
- it('Should fail import with a wrong proxy config', async function () {
- this.timeout(120000)
-
- await servers[0].kill()
- await servers[0].run({}, { env: badEnv })
-
- await quickImport(HttpStatusCode.BAD_REQUEST_400)
- })
- })
-
- describe('Object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(30000)
-
- await objectStorage.prepareDefaultMockBuckets()
- })
-
- it('Should succeed to upload to object storage with the appropriate proxy config', async function () {
- this.timeout(120000)
-
- await servers[0].kill()
- await servers[0].run(objectStorage.getDefaultMockConfig(), { env: goodEnv })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
-
- expectStartWith(video.files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
- })
-
- it('Should fail to upload to object storage with a wrong proxy config', async function () {
- this.timeout(120000)
-
- await servers[0].kill()
- await servers[0].run(objectStorage.getDefaultMockConfig(), { env: badEnv })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- await waitJobs(servers, { skipDelayed: true })
-
- const video = await servers[0].videos.get({ id: uuid })
-
- expectNotStartWith(video.files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- after(async function () {
- await proxy.terminate()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/reverse-proxy.ts b/server/tests/api/server/reverse-proxy.ts
deleted file mode 100644
index 11c96c4b5..000000000
--- a/server/tests/api/server/reverse-proxy.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test application behind a reverse proxy', function () {
- let server: PeerTubeServer
- let userAccessToken: string
- let videoId: string
-
- before(async function () {
- this.timeout(60000)
-
- const config = {
- rates_limit: {
- api: {
- max: 50,
- window: 5000
- },
- signup: {
- max: 3,
- window: 5000
- },
- login: {
- max: 20
- }
- },
- signup: {
- limit: 20
- }
- }
-
- server = await createSingleServer(1, config)
- await setAccessTokensToServers([ server ])
-
- userAccessToken = await server.users.generateUserAndToken('user')
-
- const { uuid } = await server.videos.upload()
- videoId = uuid
- })
-
- it('Should view a video only once with the same IP by default', async function () {
- this.timeout(40000)
-
- await server.views.simulateView({ id: videoId })
- await server.views.simulateView({ id: videoId })
-
- // Wait the repeatable job
- await wait(8000)
-
- const video = await server.videos.get({ id: videoId })
- expect(video.views).to.equal(1)
- })
-
- it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
- this.timeout(20000)
-
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.1,127.0.0.1' })
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.2,127.0.0.1' })
-
- // Wait the repeatable job
- await wait(8000)
-
- const video = await server.videos.get({ id: videoId })
- expect(video.views).to.equal(3)
- })
-
- it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
- this.timeout(20000)
-
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.4,0.0.0.3,::ffff:127.0.0.1' })
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.5,0.0.0.3,127.0.0.1' })
-
- // Wait the repeatable job
- await wait(8000)
-
- const video = await server.videos.get({ id: videoId })
- expect(video.views).to.equal(4)
- })
-
- it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
- this.timeout(20000)
-
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.8,0.0.0.6,127.0.0.1' })
- await server.views.simulateView({ id: videoId, xForwardedFor: '0.0.0.8,0.0.0.7,127.0.0.1' })
-
- // Wait the repeatable job
- await wait(8000)
-
- const video = await server.videos.get({ id: videoId })
- expect(video.views).to.equal(6)
- })
-
- it('Should rate limit logins', async function () {
- const user = { username: 'root', password: 'fail' }
-
- for (let i = 0; i < 18; i++) {
- await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
-
- await server.login.login({ user, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
- })
-
- it('Should rate limit signup', async function () {
- for (let i = 0; i < 10; i++) {
- try {
- await server.registrations.register({ username: 'test' + i })
- } catch {
- // empty
- }
- }
-
- await server.registrations.register({ username: 'test42', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
- })
-
- it('Should not rate limit failed signup', async function () {
- this.timeout(30000)
-
- await wait(7000)
-
- for (let i = 0; i < 3; i++) {
- await server.registrations.register({ username: 'test' + i, expectedStatus: HttpStatusCode.CONFLICT_409 })
- }
-
- await server.registrations.register({ username: 'test43', expectedStatus: HttpStatusCode.NO_CONTENT_204 })
-
- })
-
- it('Should rate limit API calls', async function () {
- this.timeout(30000)
-
- await wait(7000)
-
- for (let i = 0; i < 100; i++) {
- try {
- await server.videos.get({ id: videoId })
- } catch {
- // don't care if it fails
- }
- }
-
- await server.videos.get({ id: videoId, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
- })
-
- it('Should rate limit API calls with a user but not with an admin', async function () {
- await server.videos.get({ id: videoId, token: userAccessToken, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
-
- await server.videos.get({ id: videoId, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/services.ts b/server/tests/api/server/services.ts
deleted file mode 100644
index a10e9baed..000000000
--- a/server/tests/api/server/services.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/server-commands'
-import { Video, VideoPlaylistPrivacy } from '@shared/models'
-
-describe('Test services', function () {
- let server: PeerTubeServer = null
- let playlistUUID: string
- let playlistDisplayName: string
- let video: Video
-
- const urlSuffixes = [
- {
- input: '',
- output: ''
- },
- {
- input: '?param=1',
- output: ''
- },
- {
- input: '?muted=1&warningTitle=0&toto=1',
- output: '?muted=1&warningTitle=0'
- }
- ]
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- {
- const attributes = { name: 'my super name' }
- await server.videos.upload({ attributes })
-
- const { data } = await server.videos.list()
- video = data[0]
- }
-
- {
- const created = await server.playlists.create({
- attributes: {
- displayName: 'The Life and Times of Scrooge McDuck',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id
- }
- })
-
- playlistUUID = created.uuid
- playlistDisplayName = 'The Life and Times of Scrooge McDuck'
-
- await server.playlists.addElement({
- playlistId: created.id,
- attributes: {
- videoId: video.id
- }
- })
- }
- })
-
- it('Should have a valid oEmbed video response', async function () {
- for (const basePath of [ '/videos/watch/', '/w/' ]) {
- for (const suffix of urlSuffixes) {
- const oembedUrl = server.url + basePath + video.uuid + suffix.input
-
- const res = await server.services.getOEmbed({ oembedUrl })
- const expectedHtml = ''
-
- const expectedThumbnailUrl = 'http://' + server.host + video.previewPath
-
- expect(res.body.html).to.equal(expectedHtml)
- expect(res.body.title).to.equal(video.name)
- expect(res.body.author_name).to.equal(server.store.channel.displayName)
- expect(res.body.width).to.equal(560)
- expect(res.body.height).to.equal(315)
- expect(res.body.thumbnail_url).to.equal(expectedThumbnailUrl)
- expect(res.body.thumbnail_width).to.equal(850)
- expect(res.body.thumbnail_height).to.equal(480)
- }
- }
- })
-
- it('Should have a valid playlist oEmbed response', async function () {
- for (const basePath of [ '/videos/watch/playlist/', '/w/p/' ]) {
- for (const suffix of urlSuffixes) {
- const oembedUrl = server.url + basePath + playlistUUID + suffix.input
-
- const res = await server.services.getOEmbed({ oembedUrl })
- const expectedHtml = ''
-
- expect(res.body.html).to.equal(expectedHtml)
- expect(res.body.title).to.equal('The Life and Times of Scrooge McDuck')
- expect(res.body.author_name).to.equal(server.store.channel.displayName)
- expect(res.body.width).to.equal(560)
- expect(res.body.height).to.equal(315)
- expect(res.body.thumbnail_url).exist
- expect(res.body.thumbnail_width).to.equal(280)
- expect(res.body.thumbnail_height).to.equal(157)
- }
- }
- })
-
- it('Should have a valid oEmbed response with small max height query', async function () {
- for (const basePath of [ '/videos/watch/', '/w/' ]) {
- const oembedUrl = 'http://' + server.host + basePath + video.uuid
- const format = 'json'
- const maxHeight = 50
- const maxWidth = 50
-
- const res = await server.services.getOEmbed({ oembedUrl, format, maxHeight, maxWidth })
- const expectedHtml = ''
-
- expect(res.body.html).to.equal(expectedHtml)
- expect(res.body.title).to.equal(video.name)
- expect(res.body.author_name).to.equal(server.store.channel.displayName)
- expect(res.body.height).to.equal(50)
- expect(res.body.width).to.equal(50)
- expect(res.body).to.not.have.property('thumbnail_url')
- expect(res.body).to.not.have.property('thumbnail_width')
- expect(res.body).to.not.have.property('thumbnail_height')
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/server/slow-follows.ts b/server/tests/api/server/slow-follows.ts
deleted file mode 100644
index a967fa724..000000000
--- a/server/tests/api/server/slow-follows.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { Job } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test slow follows', function () {
- let servers: PeerTubeServer[] = []
-
- let afterFollows: Date
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
- await doubleFollow(servers[0], servers[2])
-
- afterFollows = new Date()
-
- for (let i = 0; i < 5; i++) {
- await servers[0].videos.quickUpload({ name: 'video ' + i })
- }
-
- await waitJobs(servers)
- })
-
- it('Should only have broadcast jobs', async function () {
- const { data } = await servers[0].jobs.list({ jobType: 'activitypub-http-unicast', sort: '-createdAt' })
-
- for (const job of data) {
- expect(new Date(job.createdAt)).below(afterFollows)
- }
- })
-
- it('Should process bad follower', async function () {
- this.timeout(30000)
-
- await servers[1].kill()
-
- // Set server 2 as bad follower
- await servers[0].videos.quickUpload({ name: 'video 6' })
- await waitJobs(servers[0])
-
- afterFollows = new Date()
- const filter = (job: Job) => new Date(job.createdAt) > afterFollows
-
- // Resend another broadcast job
- await servers[0].videos.quickUpload({ name: 'video 7' })
- await waitJobs(servers[0])
-
- const resBroadcast = await servers[0].jobs.list({ jobType: 'activitypub-http-broadcast', sort: '-createdAt' })
- const resUnicast = await servers[0].jobs.list({ jobType: 'activitypub-http-unicast', sort: '-createdAt' })
-
- const broadcast = resBroadcast.data.filter(filter)
- const unicast = resUnicast.data.filter(filter)
-
- expect(unicast).to.have.lengthOf(2)
- expect(broadcast).to.have.lengthOf(2)
-
- for (const u of unicast) {
- expect(u.data.uri).to.equal(servers[1].url + '/inbox')
- }
-
- for (const b of broadcast) {
- expect(b.data.uris).to.have.lengthOf(1)
- expect(b.data.uris[0]).to.equal(servers[2].url + '/inbox')
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts
deleted file mode 100644
index a1bf189fa..000000000
--- a/server/tests/api/server/stats.ts
+++ /dev/null
@@ -1,279 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { ActivityType, VideoPlaylistPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test stats (excluding redundancy)', function () {
- let servers: PeerTubeServer[] = []
- let channelId
- const user = {
- username: 'user1',
- password: 'super_password'
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
-
- await setAccessTokensToServers(servers)
- await setDefaultChannelAvatar(servers)
- await setDefaultAccountAvatar(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].users.create({ username: user.username, password: user.password })
-
- const { uuid } = await servers[0].videos.upload({ attributes: { fixture: 'video_short.webm' } })
-
- await servers[0].comments.createThread({ videoId: uuid, text: 'comment' })
-
- await servers[0].views.simulateView({ id: uuid })
-
- // Wait the video views repeatable job
- await wait(8000)
-
- await servers[2].follows.follow({ hosts: [ servers[0].url ] })
- await waitJobs(servers)
- })
-
- it('Should have the correct stats on instance 1', async function () {
- const data = await servers[0].stats.get()
-
- expect(data.totalLocalVideoComments).to.equal(1)
- expect(data.totalLocalVideos).to.equal(1)
- expect(data.totalLocalVideoViews).to.equal(1)
- expect(data.totalLocalVideoFilesSize).to.equal(218910)
- expect(data.totalUsers).to.equal(2)
- expect(data.totalVideoComments).to.equal(1)
- expect(data.totalVideos).to.equal(1)
- expect(data.totalInstanceFollowers).to.equal(2)
- expect(data.totalInstanceFollowing).to.equal(1)
- expect(data.totalLocalPlaylists).to.equal(0)
- })
-
- it('Should have the correct stats on instance 2', async function () {
- const data = await servers[1].stats.get()
-
- expect(data.totalLocalVideoComments).to.equal(0)
- expect(data.totalLocalVideos).to.equal(0)
- expect(data.totalLocalVideoViews).to.equal(0)
- expect(data.totalLocalVideoFilesSize).to.equal(0)
- expect(data.totalUsers).to.equal(1)
- expect(data.totalVideoComments).to.equal(1)
- expect(data.totalVideos).to.equal(1)
- expect(data.totalInstanceFollowers).to.equal(1)
- expect(data.totalInstanceFollowing).to.equal(1)
- expect(data.totalLocalPlaylists).to.equal(0)
- })
-
- it('Should have the correct stats on instance 3', async function () {
- const data = await servers[2].stats.get()
-
- expect(data.totalLocalVideoComments).to.equal(0)
- expect(data.totalLocalVideos).to.equal(0)
- expect(data.totalLocalVideoViews).to.equal(0)
- expect(data.totalUsers).to.equal(1)
- expect(data.totalVideoComments).to.equal(1)
- expect(data.totalVideos).to.equal(1)
- expect(data.totalInstanceFollowing).to.equal(1)
- expect(data.totalInstanceFollowers).to.equal(0)
- expect(data.totalLocalPlaylists).to.equal(0)
- })
-
- it('Should have the correct total videos stats after an unfollow', async function () {
- this.timeout(15000)
-
- await servers[2].follows.unfollow({ target: servers[0] })
- await waitJobs(servers)
-
- const data = await servers[2].stats.get()
-
- expect(data.totalVideos).to.equal(0)
- })
-
- it('Should have the correct active user stats', async function () {
- const server = servers[0]
-
- {
- const data = await server.stats.get()
-
- expect(data.totalDailyActiveUsers).to.equal(1)
- expect(data.totalWeeklyActiveUsers).to.equal(1)
- expect(data.totalMonthlyActiveUsers).to.equal(1)
- }
-
- {
- await server.login.getAccessToken(user)
-
- const data = await server.stats.get()
-
- expect(data.totalDailyActiveUsers).to.equal(2)
- expect(data.totalWeeklyActiveUsers).to.equal(2)
- expect(data.totalMonthlyActiveUsers).to.equal(2)
- }
- })
-
- it('Should have the correct active channel stats', async function () {
- const server = servers[0]
-
- {
- const data = await server.stats.get()
-
- expect(data.totalLocalVideoChannels).to.equal(2)
- expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
- expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
- expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
- }
-
- {
- const attributes = {
- name: 'stats_channel',
- displayName: 'My stats channel'
- }
- const created = await server.channels.create({ attributes })
- channelId = created.id
-
- const data = await server.stats.get()
-
- expect(data.totalLocalVideoChannels).to.equal(3)
- expect(data.totalLocalDailyActiveVideoChannels).to.equal(1)
- expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(1)
- expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(1)
- }
-
- {
- await server.videos.upload({ attributes: { fixture: 'video_short.webm', channelId } })
-
- const data = await server.stats.get()
-
- expect(data.totalLocalVideoChannels).to.equal(3)
- expect(data.totalLocalDailyActiveVideoChannels).to.equal(2)
- expect(data.totalLocalWeeklyActiveVideoChannels).to.equal(2)
- expect(data.totalLocalMonthlyActiveVideoChannels).to.equal(2)
- }
- })
-
- it('Should have the correct playlist stats', async function () {
- const server = servers[0]
-
- {
- const data = await server.stats.get()
- expect(data.totalLocalPlaylists).to.equal(0)
- }
-
- {
- await server.playlists.create({
- attributes: {
- displayName: 'playlist for count',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: channelId
- }
- })
-
- const data = await server.stats.get()
- expect(data.totalLocalPlaylists).to.equal(1)
- }
- })
-
- it('Should correctly count video file sizes if transcoding is enabled', async function () {
- this.timeout(120000)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: true
- },
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- }
- }
- }
- })
-
- await servers[0].videos.upload({ attributes: { name: 'video', fixture: 'video_short.webm' } })
-
- await waitJobs(servers)
-
- {
- const data = await servers[1].stats.get()
- expect(data.totalLocalVideoFilesSize).to.equal(0)
- }
-
- {
- const data = await servers[0].stats.get()
- expect(data.totalLocalVideoFilesSize).to.be.greaterThan(500000)
- expect(data.totalLocalVideoFilesSize).to.be.lessThan(600000)
- }
- })
-
- it('Should have the correct AP stats', async function () {
- this.timeout(120000)
-
- await servers[0].config.disableTranscoding()
-
- const first = await servers[1].stats.get()
-
- for (let i = 0; i < 10; i++) {
- await servers[0].videos.upload({ attributes: { name: 'video' } })
- }
-
- await waitJobs(servers)
-
- await wait(6000)
-
- const second = await servers[1].stats.get()
- expect(second.totalActivityPubMessagesProcessed).to.be.greaterThan(first.totalActivityPubMessagesProcessed)
-
- const apTypes: ActivityType[] = [
- 'Create', 'Update', 'Delete', 'Follow', 'Accept', 'Announce', 'Undo', 'Like', 'Reject', 'View', 'Dislike', 'Flag'
- ]
-
- const processed = apTypes.reduce(
- (previous, type) => previous + second['totalActivityPub' + type + 'MessagesSuccesses'],
- 0
- )
- expect(second.totalActivityPubMessagesProcessed).to.equal(processed)
- expect(second.totalActivityPubMessagesSuccesses).to.equal(processed)
-
- expect(second.totalActivityPubMessagesErrors).to.equal(0)
-
- for (const apType of apTypes) {
- expect(second['totalActivityPub' + apType + 'MessagesErrors']).to.equal(0)
- }
-
- await wait(6000)
-
- const third = await servers[1].stats.get()
- expect(third.totalActivityPubMessagesWaiting).to.equal(0)
- expect(third.activityPubMessagesProcessedPerSecond).to.be.lessThan(second.activityPubMessagesProcessedPerSecond)
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/server/tracker.ts b/server/tests/api/server/tracker.ts
deleted file mode 100644
index a0ce2ca35..000000000
--- a/server/tests/api/server/tracker.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await,@typescript-eslint/no-floating-promises */
-
-import { decode as magnetUriDecode, encode as magnetUriEncode } from 'magnet-uri'
-import WebTorrent from 'webtorrent'
-import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test tracker', function () {
- let server: PeerTubeServer
- let badMagnet: string
- let goodMagnet: string
-
- before(async function () {
- this.timeout(60000)
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- {
- const { uuid } = await server.videos.upload()
- const video = await server.videos.get({ id: uuid })
- goodMagnet = video.files[0].magnetUri
-
- const parsed = magnetUriDecode(goodMagnet)
- parsed.infoHash = '010597bb88b1968a5693a4fa8267c592ca65f2e9'
-
- badMagnet = magnetUriEncode(parsed)
- }
- })
-
- it('Should succeed with the correct infohash', function (done) {
- const webtorrent = new WebTorrent()
-
- const torrent = webtorrent.add(goodMagnet)
-
- torrent.on('error', done)
- torrent.on('warning', warn => {
- const message = typeof warn === 'string' ? warn : warn.message
- if (message.includes('Unknown infoHash ')) return done(new Error('Error on infohash'))
- })
-
- torrent.on('done', done)
- })
-
- it('Should disable the tracker', function (done) {
- this.timeout(20000)
-
- const errCb = () => done(new Error('Tracker is enabled'))
-
- killallServers([ server ])
- .then(() => server.run({ tracker: { enabled: false } }))
- .then(() => {
- const webtorrent = new WebTorrent()
-
- const torrent = webtorrent.add(goodMagnet)
-
- torrent.on('error', done)
- torrent.on('warning', warn => {
- const message = typeof warn === 'string' ? warn : warn.message
- if (message.includes('disabled ')) {
- torrent.off('done', errCb)
-
- return done()
- }
- })
-
- torrent.on('done', errCb)
- })
- })
-
- it('Should return an error when adding an incorrect infohash', function (done) {
- this.timeout(20000)
-
- killallServers([ server ])
- .then(() => server.run())
- .then(() => {
- const webtorrent = new WebTorrent()
-
- const torrent = webtorrent.add(badMagnet)
-
- torrent.on('error', done)
- torrent.on('warning', warn => {
- const message = typeof warn === 'string' ? warn : warn.message
- if (message.includes('Unknown infoHash ')) return done()
- })
-
- torrent.on('done', () => done(new Error('No error on infohash')))
- })
- })
-
- it('Should block the IP after the failed infohash', function (done) {
- const webtorrent = new WebTorrent()
-
- const torrent = webtorrent.add(goodMagnet)
-
- torrent.on('error', done)
- torrent.on('warning', warn => {
- const message = typeof warn === 'string' ? warn : warn.message
- if (message.includes('Unsupported tracker protocol')) return done()
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/transcoding/audio-only.ts b/server/tests/api/transcoding/audio-only.ts
deleted file mode 100644
index f4cc012ef..000000000
--- a/server/tests/api/transcoding/audio-only.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { getAudioStream, getVideoStreamDimensionsInfo } from '@shared/ffmpeg'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test audio only video transcoding', function () {
- let servers: PeerTubeServer[] = []
- let videoUUID: string
- let webVideoAudioFileUrl: string
- let fragmentedAudioFileUrl: string
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = {
- transcoding: {
- enabled: true,
- resolutions: {
- '0p': true,
- '144p': false,
- '240p': true,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- hls: {
- enabled: true
- },
- web_videos: {
- enabled: true
- }
- }
- }
- servers = await createMultipleServers(2, configOverride)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should upload a video and transcode it', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'audio only' } })
- videoUUID = uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- for (const files of [ video.files, video.streamingPlaylists[0].files ]) {
- expect(files).to.have.lengthOf(3)
- expect(files[0].resolution.id).to.equal(720)
- expect(files[1].resolution.id).to.equal(240)
- expect(files[2].resolution.id).to.equal(0)
- }
-
- if (server.serverNumber === 1) {
- webVideoAudioFileUrl = video.files[2].fileUrl
- fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl
- }
- }
- })
-
- it('0p transcoded video should not have video', async function () {
- const paths = [
- servers[0].servers.buildWebVideoFilePath(webVideoAudioFileUrl),
- servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl)
- ]
-
- for (const path of paths) {
- const { audioStream } = await getAudioStream(path)
- expect(audioStream['codec_name']).to.be.equal('aac')
- expect(audioStream['bit_rate']).to.be.at.most(384 * 8000)
-
- const size = await getVideoStreamDimensionsInfo(path)
-
- expect(size.height).to.equal(0)
- expect(size.width).to.equal(0)
- expect(size.isPortraitMode).to.be.false
- expect(size.ratio).to.equal(0)
- expect(size.resolution).to.equal(0)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/transcoding/create-transcoding.ts b/server/tests/api/transcoding/create-transcoding.ts
deleted file mode 100644
index 9a891043c..000000000
--- a/server/tests/api/transcoding/create-transcoding.ts
+++ /dev/null
@@ -1,266 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkResolutionsInMasterPlaylist, expectStartWith } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoDetails } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createMultipleServers,
- doubleFollow,
- expectNoFailedTranscodingJob,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkFilesInObjectStorage (objectStorage: ObjectStorageCommand, video: VideoDetails) {
- for (const file of video.files) {
- expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- if (video.streamingPlaylists.length === 0) return
-
- const hlsPlaylist = video.streamingPlaylists[0]
- for (const file of hlsPlaylist.files) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- expectStartWith(hlsPlaylist.playlistUrl, objectStorage.getMockPlaylistBaseUrl())
- await makeRawRequest({ url: hlsPlaylist.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- expectStartWith(hlsPlaylist.segmentsSha256Url, objectStorage.getMockPlaylistBaseUrl())
- await makeRawRequest({ url: hlsPlaylist.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
-}
-
-function runTests (enableObjectStorage: boolean) {
- let servers: PeerTubeServer[] = []
- let videoUUID: string
- let publishedAt: string
-
- let shouldBeDeleted: string[]
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- const config = enableObjectStorage
- ? objectStorage.getDefaultMockConfig()
- : {}
-
- // Run server 2 to have transcoding enabled
- servers = await createMultipleServers(2, config)
- await setAccessTokensToServers(servers)
-
- await servers[0].config.disableTranscoding()
-
- await doubleFollow(servers[0], servers[1])
-
- if (enableObjectStorage) await objectStorage.prepareDefaultMockBuckets()
-
- const { shortUUID } = await servers[0].videos.quickUpload({ name: 'video' })
- videoUUID = shortUUID
-
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: videoUUID })
- publishedAt = video.publishedAt as string
-
- await servers[0].config.enableTranscoding()
- })
-
- it('Should generate HLS', async function () {
- this.timeout(60000)
-
- await servers[0].videos.runTranscoding({
- videoId: videoUUID,
- transcodingType: 'hls'
- })
-
- await waitJobs(servers)
- await expectNoFailedTranscodingJob(servers[0])
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- expect(videoDetails.files).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5)
-
- if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
- }
- })
-
- it('Should generate Web Video', async function () {
- this.timeout(60000)
-
- await servers[0].videos.runTranscoding({
- videoId: videoUUID,
- transcodingType: 'web-video'
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- expect(videoDetails.files).to.have.lengthOf(5)
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5)
-
- if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
- }
- })
-
- it('Should generate Web Video from HLS only video', async function () {
- this.timeout(60000)
-
- await servers[0].videos.removeAllWebVideoFiles({ videoId: videoUUID })
- await waitJobs(servers)
-
- await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- expect(videoDetails.files).to.have.lengthOf(5)
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5)
-
- if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
- }
- })
-
- it('Should only generate Web Video', async function () {
- this.timeout(60000)
-
- await servers[0].videos.removeHLSPlaylist({ videoId: videoUUID })
- await waitJobs(servers)
-
- await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- expect(videoDetails.files).to.have.lengthOf(5)
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(0)
-
- if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
- }
- })
-
- it('Should correctly update HLS playlist on resolution change', async function () {
- this.timeout(120000)
-
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- resolutions: ConfigCommand.getCustomConfigResolutions(false),
-
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: true
- }
- }
- }
- })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'quick' })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: uuid })
-
- expect(videoDetails.files).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(1)
-
- if (enableObjectStorage) await checkFilesInObjectStorage(objectStorage, videoDetails)
-
- shouldBeDeleted = [
- videoDetails.streamingPlaylists[0].files[0].fileUrl,
- videoDetails.streamingPlaylists[0].playlistUrl,
- videoDetails.streamingPlaylists[0].segmentsSha256Url
- ]
- }
-
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- resolutions: ConfigCommand.getCustomConfigResolutions(true),
-
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: true
- }
- }
- }
- })
-
- await servers[0].videos.runTranscoding({ videoId: uuid, transcodingType: 'hls' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: uuid })
-
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
- expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5)
-
- if (enableObjectStorage) {
- await checkFilesInObjectStorage(objectStorage, videoDetails)
-
- const hlsPlaylist = videoDetails.streamingPlaylists[0]
- const resolutions = hlsPlaylist.files.map(f => f.resolution.id)
- await checkResolutionsInMasterPlaylist({ server: servers[0], playlistUrl: hlsPlaylist.playlistUrl, resolutions })
-
- const shaBody = await servers[0].streamingPlaylists.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url, withRetry: true })
- expect(Object.keys(shaBody)).to.have.lengthOf(5)
- }
- }
- })
-
- it('Should have correctly deleted previous files', async function () {
- for (const fileUrl of shouldBeDeleted) {
- await makeRawRequest({ url: fileUrl, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
-
- it('Should not have updated published at attributes', async function () {
- const video = await servers[0].videos.get({ id: videoUUID })
-
- expect(video.publishedAt).to.equal(publishedAt)
- })
-
- after(async function () {
- if (objectStorage) await objectStorage.cleanupMock()
-
- await cleanupTests(servers)
- })
-}
-
-describe('Test create transcoding jobs from API', function () {
-
- describe('On filesystem', function () {
- runTests(false)
- })
-
- describe('On object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- runTests(true)
- })
-})
diff --git a/server/tests/api/transcoding/hls.ts b/server/tests/api/transcoding/hls.ts
deleted file mode 100644
index d67043c2a..000000000
--- a/server/tests/api/transcoding/hls.ts
+++ /dev/null
@@ -1,175 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { join } from 'path'
-import { checkDirectoryIsEmpty, checkTmpIsEmpty, completeCheckHlsPlaylist } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
-
-describe('Test HLS videos', function () {
- let servers: PeerTubeServer[] = []
-
- function runTestSuite (hlsOnly: boolean, objectStorageBaseUrl?: string) {
- const videoUUIDs: string[] = []
-
- it('Should upload a video and transcode it to HLS', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video 1', fixture: 'video_short.webm' } })
- videoUUIDs.push(uuid)
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl })
- })
-
- it('Should upload an audio file and transcode it to HLS', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video audio', fixture: 'sample.ogg' } })
- videoUUIDs.push(uuid)
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({
- servers,
- videoUUID: uuid,
- hlsOnly,
- resolutions: [ DEFAULT_AUDIO_RESOLUTION, 360, 240 ],
- objectStorageBaseUrl
- })
- })
-
- it('Should update the video', async function () {
- this.timeout(30000)
-
- await servers[0].videos.update({ id: videoUUIDs[0], attributes: { name: 'video 1 updated' } })
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({ servers, videoUUID: videoUUIDs[0], hlsOnly, objectStorageBaseUrl })
- })
-
- it('Should delete videos', async function () {
- for (const uuid of videoUUIDs) {
- await servers[0].videos.remove({ id: uuid })
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- for (const uuid of videoUUIDs) {
- await server.videos.get({ id: uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- }
- })
-
- it('Should have the playlists/segment deleted from the disk', async function () {
- for (const server of servers) {
- await checkDirectoryIsEmpty(server, 'web-videos', [ 'private' ])
- await checkDirectoryIsEmpty(server, join('web-videos', 'private'))
-
- await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls'), [ 'private' ])
- await checkDirectoryIsEmpty(server, join('streaming-playlists', 'hls', 'private'))
- }
- })
-
- it('Should have an empty tmp directory', async function () {
- for (const server of servers) {
- await checkTmpIsEmpty(server)
- }
- })
- }
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = {
- transcoding: {
- enabled: true,
- allow_audio_files: true,
- hls: {
- enabled: true
- }
- }
- }
- servers = await createMultipleServers(2, configOverride)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('With Web Video & HLS enabled', function () {
- runTestSuite(false)
- })
-
- describe('With only HLS enabled', function () {
-
- before(async function () {
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- allowAudioFiles: true,
- resolutions: {
- '144p': false,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- hls: {
- enabled: true
- },
- webVideos: {
- enabled: false
- }
- }
- }
- })
- })
-
- runTestSuite(true)
- })
-
- describe('With object storage enabled', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = objectStorage.getDefaultMockConfig()
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
- await servers[0].run(configOverride)
- })
-
- runTestSuite(true, objectStorage.getMockPlaylistBaseUrl())
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/transcoding/index.ts b/server/tests/api/transcoding/index.ts
deleted file mode 100644
index 9866418d6..000000000
--- a/server/tests/api/transcoding/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from './audio-only'
-export * from './create-transcoding'
-export * from './hls'
-export * from './transcoder'
-export * from './update-while-transcoding'
-export * from './video-studio'
diff --git a/server/tests/api/transcoding/transcoder.ts b/server/tests/api/transcoding/transcoder.ts
deleted file mode 100644
index 5386d236f..000000000
--- a/server/tests/api/transcoding/transcoder.ts
+++ /dev/null
@@ -1,800 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { canDoQuickTranscode } from '@server/lib/transcoding/transcoding-quick-transcode'
-import { checkWebTorrentWorks, generateHighBitrateVideo, generateVideoWithFramerate } from '@server/tests/shared'
-import { buildAbsoluteFixturePath, getAllFiles, getMaxTheoreticalBitrate, getMinTheoreticalBitrate, omit } from '@shared/core-utils'
-import {
- ffprobePromise,
- getAudioStream,
- getVideoStreamBitrate,
- getVideoStreamDimensionsInfo,
- getVideoStreamFPS,
- hasAudioStream
-} from '@shared/ffmpeg'
-import { HttpStatusCode, VideoFileMetadata, VideoState } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-function updateConfigForTranscoding (server: PeerTubeServer) {
- return server.config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- allowAdditionalExtensions: true,
- allowAudioFiles: true,
- hls: { enabled: true },
- webVideos: { enabled: true },
- resolutions: {
- '0p': false,
- '144p': true,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- }
- }
- }
- })
-}
-
-describe('Test video transcoding', function () {
- let servers: PeerTubeServer[] = []
- let video4k: string
-
- before(async function () {
- this.timeout(30_000)
-
- // Run servers
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await updateConfigForTranscoding(servers[1])
- })
-
- describe('Basic transcoding (or not)', function () {
-
- it('Should not transcode video on server 1', async function () {
- this.timeout(60_000)
-
- const attributes = {
- name: 'my super name for server 1',
- description: 'my super description for server 1',
- fixture: 'video_short.webm'
- }
- await servers[0].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- const video = data[0]
-
- const videoDetails = await server.videos.get({ id: video.id })
- expect(videoDetails.files).to.have.lengthOf(1)
-
- const magnetUri = videoDetails.files[0].magnetUri
- expect(magnetUri).to.match(/\.webm/)
-
- await checkWebTorrentWorks(magnetUri, /\.webm$/)
- }
- })
-
- it('Should transcode video on server 2', async function () {
- this.timeout(120_000)
-
- const attributes = {
- name: 'my super name for server 2',
- description: 'my super description for server 2',
- fixture: 'video_short.webm'
- }
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(5)
-
- const magnetUri = videoDetails.files[0].magnetUri
- expect(magnetUri).to.match(/\.mp4/)
-
- await checkWebTorrentWorks(magnetUri, /\.mp4$/)
- }
- })
-
- it('Should wait for transcoding before publishing the video', async function () {
- this.timeout(160_000)
-
- {
- // Upload the video, but wait transcoding
- const attributes = {
- name: 'waiting video',
- fixture: 'video_short1.webm',
- waitTranscoding: true
- }
- const { uuid } = await servers[1].videos.upload({ attributes })
- const videoId = uuid
-
- // Should be in transcode state
- const body = await servers[1].videos.get({ id: videoId })
- expect(body.name).to.equal('waiting video')
- expect(body.state.id).to.equal(VideoState.TO_TRANSCODE)
- expect(body.state.label).to.equal('To transcode')
- expect(body.waitTranscoding).to.be.true
-
- {
- // Should have my video
- const { data } = await servers[1].videos.listMyVideos()
- const videoToFindInMine = data.find(v => v.name === attributes.name)
- expect(videoToFindInMine).not.to.be.undefined
- expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE)
- expect(videoToFindInMine.state.label).to.equal('To transcode')
- expect(videoToFindInMine.waitTranscoding).to.be.true
- }
-
- {
- // Should not list this video
- const { data } = await servers[1].videos.list()
- const videoToFindInList = data.find(v => v.name === attributes.name)
- expect(videoToFindInList).to.be.undefined
- }
-
- // Server 1 should not have the video yet
- await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- const videoToFind = data.find(v => v.name === 'waiting video')
- expect(videoToFind).not.to.be.undefined
-
- const videoDetails = await server.videos.get({ id: videoToFind.id })
-
- expect(videoDetails.state.id).to.equal(VideoState.PUBLISHED)
- expect(videoDetails.state.label).to.equal('Published')
- expect(videoDetails.waitTranscoding).to.be.true
- }
- })
-
- it('Should accept and transcode additional extensions', async function () {
- this.timeout(300_000)
-
- for (const fixture of [ 'video_short.mkv', 'video_short.avi' ]) {
- const attributes = {
- name: fixture,
- fixture
- }
-
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
- expect(videoDetails.files).to.have.lengthOf(5)
-
- const magnetUri = videoDetails.files[0].magnetUri
- expect(magnetUri).to.contain('.mp4')
- }
- }
- })
-
- it('Should transcode a 4k video', async function () {
- this.timeout(200_000)
-
- const attributes = {
- name: '4k video',
- fixture: 'video_short_4k.mp4'
- }
-
- const { uuid } = await servers[1].videos.upload({ attributes })
- video4k = uuid
-
- await waitJobs(servers)
-
- const resolutions = [ 144, 240, 360, 480, 720, 1080, 1440, 2160 ]
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: video4k })
- expect(videoDetails.files).to.have.lengthOf(resolutions.length)
-
- for (const r of resolutions) {
- expect(videoDetails.files.find(f => f.resolution.id === r)).to.not.be.undefined
- expect(videoDetails.streamingPlaylists[0].files.find(f => f.resolution.id === r)).to.not.be.undefined
- }
- }
- })
- })
-
- describe('Audio transcoding', function () {
-
- it('Should transcode high bit rate mp3 to proper bit rate', async function () {
- this.timeout(60_000)
-
- const attributes = {
- name: 'mp3_256k',
- fixture: 'video_short_mp3_256k.mp4'
- }
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(5)
-
- const file = videoDetails.files.find(f => f.resolution.id === 240)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const probe = await getAudioStream(path)
-
- if (probe.audioStream) {
- expect(probe.audioStream['codec_name']).to.be.equal('aac')
- expect(probe.audioStream['bit_rate']).to.be.at.most(384 * 8000)
- } else {
- this.fail('Could not retrieve the audio stream on ' + probe.absolutePath)
- }
- }
- })
-
- it('Should transcode video with no audio and have no audio itself', async function () {
- this.timeout(60_000)
-
- const attributes = {
- name: 'no_audio',
- fixture: 'video_short_no_audio.mp4'
- }
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
-
- const file = videoDetails.files.find(f => f.resolution.id === 240)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
-
- expect(await hasAudioStream(path)).to.be.false
- }
- })
-
- it('Should leave the audio untouched, but properly transcode the video', async function () {
- this.timeout(60_000)
-
- const attributes = {
- name: 'untouched_audio',
- fixture: 'video_short.mp4'
- }
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(5)
-
- const fixturePath = buildAbsoluteFixturePath(attributes.fixture)
- const fixtureVideoProbe = await getAudioStream(fixturePath)
-
- const file = videoDetails.files.find(f => f.resolution.id === 240)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
-
- const videoProbe = await getAudioStream(path)
-
- if (videoProbe.audioStream && fixtureVideoProbe.audioStream) {
- const toOmit = [ 'max_bit_rate', 'duration', 'duration_ts', 'nb_frames', 'start_time', 'start_pts' ]
- expect(omit(videoProbe.audioStream, toOmit)).to.be.deep.equal(omit(fixtureVideoProbe.audioStream, toOmit))
- } else {
- this.fail('Could not retrieve the audio stream on ' + videoProbe.absolutePath)
- }
- }
- })
- })
-
- describe('Audio upload', function () {
-
- function runSuite (mode: 'legacy' | 'resumable') {
-
- before(async function () {
- await servers[1].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- hls: { enabled: true },
- webVideos: { enabled: true },
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- }
- }
- }
- })
- })
-
- it('Should merge an audio file with the preview file', async function () {
- this.timeout(60_000)
-
- const attributes = { name: 'audio_with_preview', previewfile: 'custom-preview.jpg', fixture: 'sample.ogg' }
- await servers[1].videos.upload({ attributes, mode })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === 'audio_with_preview')
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(1)
-
- await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
-
- const magnetUri = videoDetails.files[0].magnetUri
- expect(magnetUri).to.contain('.mp4')
- }
- })
-
- it('Should upload an audio file and choose a default background image', async function () {
- this.timeout(60_000)
-
- const attributes = { name: 'audio_without_preview', fixture: 'sample.ogg' }
- await servers[1].videos.upload({ attributes, mode })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === 'audio_without_preview')
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(1)
-
- await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
-
- const magnetUri = videoDetails.files[0].magnetUri
- expect(magnetUri).to.contain('.mp4')
- }
- })
-
- it('Should upload an audio file and create an audio version only', async function () {
- this.timeout(60_000)
-
- await servers[1].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- hls: { enabled: true },
- webVideos: { enabled: true },
- resolutions: {
- '0p': true,
- '144p': false,
- '240p': false,
- '360p': false
- }
- }
- }
- })
-
- const attributes = { name: 'audio_with_preview', previewfile: 'custom-preview.jpg', fixture: 'sample.ogg' }
- const { id } = await servers[1].videos.upload({ attributes, mode })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id })
-
- for (const files of [ videoDetails.files, videoDetails.streamingPlaylists[0].files ]) {
- expect(files).to.have.lengthOf(2)
- expect(files.find(f => f.resolution.id === 0)).to.not.be.undefined
- }
- }
-
- await updateConfigForTranscoding(servers[1])
- })
- }
-
- describe('Legacy upload', function () {
- runSuite('legacy')
- })
-
- describe('Resumable upload', function () {
- runSuite('resumable')
- })
- })
-
- describe('Framerate', function () {
-
- it('Should transcode a 60 FPS video', async function () {
- this.timeout(60_000)
-
- const attributes = {
- name: 'my super 30fps name for server 2',
- description: 'my super 30fps description for server 2',
- fixture: '60fps_720p_small.mp4'
- }
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.name === attributes.name)
- const videoDetails = await server.videos.get({ id: video.id })
-
- expect(videoDetails.files).to.have.lengthOf(5)
- expect(videoDetails.files[0].fps).to.be.above(58).and.below(62)
- expect(videoDetails.files[1].fps).to.be.below(31)
- expect(videoDetails.files[2].fps).to.be.below(31)
- expect(videoDetails.files[3].fps).to.be.below(31)
- expect(videoDetails.files[4].fps).to.be.below(31)
-
- for (const resolution of [ 144, 240, 360, 480 ]) {
- const file = videoDetails.files.find(f => f.resolution.id === resolution)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const fps = await getVideoStreamFPS(path)
-
- expect(fps).to.be.below(31)
- }
-
- const file = videoDetails.files.find(f => f.resolution.id === 720)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const fps = await getVideoStreamFPS(path)
-
- expect(fps).to.be.above(58).and.below(62)
- }
- })
-
- it('Should downscale to the closest divisor standard framerate', async function () {
- this.timeout(200_000)
-
- let tempFixturePath: string
-
- {
- tempFixturePath = await generateVideoWithFramerate(59)
-
- const fps = await getVideoStreamFPS(tempFixturePath)
- expect(fps).to.be.equal(59)
- }
-
- const attributes = {
- name: '59fps video',
- description: '59fps video',
- fixture: tempFixturePath
- }
-
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const { id } = data.find(v => v.name === attributes.name)
- const video = await server.videos.get({ id })
-
- {
- const file = video.files.find(f => f.resolution.id === 240)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const fps = await getVideoStreamFPS(path)
- expect(fps).to.be.equal(25)
- }
-
- {
- const file = video.files.find(f => f.resolution.id === 720)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const fps = await getVideoStreamFPS(path)
- expect(fps).to.be.equal(59)
- }
- }
- })
- })
-
- describe('Bitrate control', function () {
-
- it('Should respect maximum bitrate values', async function () {
- this.timeout(160_000)
-
- const tempFixturePath = await generateHighBitrateVideo()
-
- const attributes = {
- name: 'high bitrate video',
- description: 'high bitrate video',
- fixture: tempFixturePath
- }
-
- await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const { id } = data.find(v => v.name === attributes.name)
- const video = await server.videos.get({ id })
-
- for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
- const file = video.files.find(f => f.resolution.id === resolution)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
-
- const bitrate = await getVideoStreamBitrate(path)
- const fps = await getVideoStreamFPS(path)
- const dataResolution = await getVideoStreamDimensionsInfo(path)
-
- expect(resolution).to.equal(resolution)
-
- const maxBitrate = getMaxTheoreticalBitrate({ ...dataResolution, fps })
- expect(bitrate).to.be.below(maxBitrate)
- }
- }
- })
-
- it('Should not transcode to an higher bitrate than the original file but above our low limit', async function () {
- this.timeout(160_000)
-
- const newConfig = {
- transcoding: {
- enabled: true,
- resolutions: {
- '144p': true,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- webVideos: { enabled: true },
- hls: { enabled: true }
- }
- }
- await servers[1].config.updateCustomSubConfig({ newConfig })
-
- const attributes = {
- name: 'low bitrate',
- fixture: 'low-bitrate.mp4'
- }
-
- const { id } = await servers[1].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- const video = await servers[1].videos.get({ id })
-
- const resolutions = [ 240, 360, 480, 720, 1080 ]
- for (const r of resolutions) {
- const file = video.files.find(f => f.resolution.id === r)
-
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
- const bitrate = await getVideoStreamBitrate(path)
-
- const inputBitrate = 60_000
- const limit = getMinTheoreticalBitrate({ fps: 10, ratio: 1, resolution: r })
- let belowValue = Math.max(inputBitrate, limit)
- belowValue += belowValue * 0.20 // Apply 20% margin because bitrate control is not very precise
-
- expect(bitrate, `${path} not below ${limit}`).to.be.below(belowValue)
- }
- })
- })
-
- describe('FFprobe', function () {
-
- it('Should provide valid ffprobe data', async function () {
- this.timeout(160_000)
-
- const videoUUID = (await servers[1].videos.quickUpload({ name: 'ffprobe data' })).uuid
- await waitJobs(servers)
-
- {
- const video = await servers[1].videos.get({ id: videoUUID })
- const file = video.files.find(f => f.resolution.id === 240)
- const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
-
- const probe = await ffprobePromise(path)
- const metadata = new VideoFileMetadata(probe)
-
- // expected format properties
- for (const p of [
- 'tags.encoder',
- 'format_long_name',
- 'size',
- 'bit_rate'
- ]) {
- expect(metadata.format).to.have.nested.property(p)
- }
-
- // expected stream properties
- for (const p of [
- 'codec_long_name',
- 'profile',
- 'width',
- 'height',
- 'display_aspect_ratio',
- 'avg_frame_rate',
- 'pix_fmt'
- ]) {
- expect(metadata.streams[0]).to.have.nested.property(p)
- }
-
- expect(metadata).to.not.have.nested.property('format.filename')
- }
-
- for (const server of servers) {
- const videoDetails = await server.videos.get({ id: videoUUID })
-
- const videoFiles = getAllFiles(videoDetails)
- expect(videoFiles).to.have.lengthOf(10)
-
- for (const file of videoFiles) {
- expect(file.metadata).to.be.undefined
- expect(file.metadataUrl).to.exist
- expect(file.metadataUrl).to.contain(servers[1].url)
- expect(file.metadataUrl).to.contain(videoUUID)
-
- const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
- expect(metadata).to.have.nested.property('format.size')
- }
- }
- })
-
- it('Should correctly detect if quick transcode is possible', async function () {
- this.timeout(10_000)
-
- expect(await canDoQuickTranscode(buildAbsoluteFixturePath('video_short.mp4'))).to.be.true
- expect(await canDoQuickTranscode(buildAbsoluteFixturePath('video_short.webm'))).to.be.false
- })
- })
-
- describe('Transcoding job queue', function () {
-
- it('Should have the appropriate priorities for transcoding jobs', async function () {
- const body = await servers[1].jobs.list({
- start: 0,
- count: 100,
- sort: 'createdAt',
- jobType: 'video-transcoding'
- })
-
- const jobs = body.data
- const transcodingJobs = jobs.filter(j => j.data.videoUUID === video4k)
-
- expect(transcodingJobs).to.have.lengthOf(16)
-
- const hlsJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-hls')
- const webVideoJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-web-video')
- const optimizeJobs = transcodingJobs.filter(j => j.data.type === 'optimize-to-web-video')
-
- expect(hlsJobs).to.have.lengthOf(8)
- expect(webVideoJobs).to.have.lengthOf(7)
- expect(optimizeJobs).to.have.lengthOf(1)
-
- for (const j of optimizeJobs.concat(hlsJobs.concat(webVideoJobs))) {
- expect(j.priority).to.be.greaterThan(100)
- expect(j.priority).to.be.lessThan(150)
- }
- })
- })
-
- describe('Bounded transcoding', function () {
-
- it('Should not generate an upper resolution than original file', async function () {
- this.timeout(120_000)
-
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- hls: { enabled: true },
- webVideos: { enabled: true },
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': true,
- '360p': false,
- '480p': true,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- alwaysTranscodeOriginalResolution: false
- }
- }
- })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video', fixture: 'video_short.webm' })
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
- const hlsFiles = video.streamingPlaylists[0].files
-
- expect(video.files).to.have.lengthOf(2)
- expect(hlsFiles).to.have.lengthOf(2)
-
- // eslint-disable-next-line @typescript-eslint/require-array-sort-compare
- const resolutions = getAllFiles(video).map(f => f.resolution.id).sort()
- expect(resolutions).to.deep.equal([ 240, 240, 480, 480 ])
- })
-
- it('Should only keep the original resolution if all resolutions are disabled', async function () {
- this.timeout(120_000)
-
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- resolutions: {
- '0p': false,
- '144p': false,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- }
- }
- }
- })
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video', fixture: 'video_short.webm' })
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
- const hlsFiles = video.streamingPlaylists[0].files
-
- expect(video.files).to.have.lengthOf(1)
- expect(hlsFiles).to.have.lengthOf(1)
-
- expect(video.files[0].resolution.id).to.equal(720)
- expect(hlsFiles[0].resolution.id).to.equal(720)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/transcoding/update-while-transcoding.ts b/server/tests/api/transcoding/update-while-transcoding.ts
deleted file mode 100644
index cfb4fa0cc..000000000
--- a/server/tests/api/transcoding/update-while-transcoding.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { completeCheckHlsPlaylist } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled, wait } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test update video privacy while transcoding', function () {
- let servers: PeerTubeServer[] = []
-
- const videoUUIDs: string[] = []
-
- function runTestSuite (hlsOnly: boolean, objectStorageBaseUrl?: string) {
-
- it('Should not have an error while quickly updating a private video to public after upload #1', async function () {
- this.timeout(360_000)
-
- const attributes = {
- name: 'quick update',
- privacy: VideoPrivacy.PRIVATE
- }
-
- const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: false })
- await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
- videoUUIDs.push(uuid)
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl })
- })
-
- it('Should not have an error while quickly updating a private video to public after upload #2', async function () {
- this.timeout(60000)
-
- {
- const attributes = {
- name: 'quick update 2',
- privacy: VideoPrivacy.PRIVATE
- }
-
- const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: true })
- await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
- videoUUIDs.push(uuid)
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl })
- }
- })
-
- it('Should not have an error while quickly updating a private video to public after upload #3', async function () {
- this.timeout(60000)
-
- const attributes = {
- name: 'quick update 3',
- privacy: VideoPrivacy.PRIVATE
- }
-
- const { uuid } = await servers[0].videos.upload({ attributes, waitTorrentGeneration: true })
- await wait(1000)
- await servers[0].videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
- videoUUIDs.push(uuid)
-
- await waitJobs(servers)
-
- await completeCheckHlsPlaylist({ servers, videoUUID: uuid, hlsOnly, objectStorageBaseUrl })
- })
- }
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = {
- transcoding: {
- enabled: true,
- allow_audio_files: true,
- hls: {
- enabled: true
- }
- }
- }
- servers = await createMultipleServers(2, configOverride)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('With Web Video & HLS enabled', function () {
- runTestSuite(false)
- })
-
- describe('With only HLS enabled', function () {
-
- before(async function () {
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- allowAudioFiles: true,
- resolutions: {
- '144p': false,
- '240p': true,
- '360p': true,
- '480p': true,
- '720p': true,
- '1080p': true,
- '1440p': true,
- '2160p': true
- },
- hls: {
- enabled: true
- },
- webVideos: {
- enabled: false
- }
- }
- }
- })
- })
-
- runTestSuite(true)
- })
-
- describe('With object storage enabled', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = objectStorage.getDefaultMockConfig()
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
- await servers[0].run(configOverride)
- })
-
- runTestSuite(true, objectStorage.getMockPlaylistBaseUrl())
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/transcoding/video-studio.ts b/server/tests/api/transcoding/video-studio.ts
deleted file mode 100644
index ba68f8e24..000000000
--- a/server/tests/api/transcoding/video-studio.ts
+++ /dev/null
@@ -1,377 +0,0 @@
-import { expect } from 'chai'
-import { checkPersistentTmpIsEmpty, checkVideoDuration, expectStartWith } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils'
-import { VideoStudioTask } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- VideoStudioCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video studio', function () {
- let servers: PeerTubeServer[] = []
- let videoUUID: string
-
- async function renewVideo (fixture = 'video_short.webm') {
- const video = await servers[0].videos.quickUpload({ name: 'video', fixture })
- videoUUID = video.uuid
-
- await waitJobs(servers)
- }
-
- async function createTasks (tasks: VideoStudioTask[]) {
- await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks })
- await waitJobs(servers)
- }
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableMinimumTranscoding()
-
- await servers[0].config.enableStudio()
- })
-
- describe('Cutting', function () {
-
- it('Should cut the beginning of the video', async function () {
- this.timeout(120_000)
-
- await renewVideo()
- await waitJobs(servers)
-
- const beforeTasks = new Date()
-
- await createTasks([
- {
- name: 'cut',
- options: {
- start: 2
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 3)
-
- const video = await server.videos.get({ id: videoUUID })
- expect(new Date(video.publishedAt)).to.be.below(beforeTasks)
- }
- })
-
- it('Should cut the end of the video', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- await createTasks([
- {
- name: 'cut',
- options: {
- end: 2
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 2)
- }
- })
-
- it('Should cut start/end of the video', async function () {
- this.timeout(120_000)
- await renewVideo('video_short1.webm') // 10 seconds video duration
-
- await createTasks([
- {
- name: 'cut',
- options: {
- start: 2,
- end: 6
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 4)
- }
- })
- })
-
- describe('Intro/Outro', function () {
-
- it('Should add an intro', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- await createTasks([
- {
- name: 'add-intro',
- options: {
- file: 'video_short.webm'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 10)
- }
- })
-
- it('Should add an outro', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- await createTasks([
- {
- name: 'add-outro',
- options: {
- file: 'video_very_short_240p.mp4'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 7)
- }
- })
-
- it('Should add an intro/outro', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- await createTasks([
- {
- name: 'add-intro',
- options: {
- file: 'video_very_short_240p.mp4'
- }
- },
- {
- name: 'add-outro',
- options: {
- // Different frame rate
- file: 'video_short2.webm'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 12)
- }
- })
-
- it('Should add an intro to a video without audio', async function () {
- this.timeout(120_000)
- await renewVideo('video_short_no_audio.mp4')
-
- await createTasks([
- {
- name: 'add-intro',
- options: {
- file: 'video_very_short_240p.mp4'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 7)
- }
- })
-
- it('Should add an outro without audio to a video with audio', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- await createTasks([
- {
- name: 'add-outro',
- options: {
- file: 'video_short_no_audio.mp4'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 10)
- }
- })
-
- it('Should add an outro without audio to a video with audio', async function () {
- this.timeout(120_000)
- await renewVideo('video_short_no_audio.mp4')
-
- await createTasks([
- {
- name: 'add-outro',
- options: {
- file: 'video_short_no_audio.mp4'
- }
- }
- ])
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 10)
- }
- })
- })
-
- describe('Watermark', function () {
-
- it('Should add a watermark to the video', async function () {
- this.timeout(120_000)
- await renewVideo()
-
- const video = await servers[0].videos.get({ id: videoUUID })
- const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
-
- await createTasks([
- {
- name: 'add-watermark',
- options: {
- file: 'custom-thumbnail.png'
- }
- }
- ])
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- const fileUrls = getAllFiles(video).map(f => f.fileUrl)
-
- for (const oldUrl of oldFileUrls) {
- expect(fileUrls).to.not.include(oldUrl)
- }
- }
- })
- })
-
- describe('Complex tasks', function () {
- it('Should run a complex task', async function () {
- this.timeout(240_000)
- await renewVideo()
-
- await createTasks(VideoStudioCommand.getComplexTask())
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 9)
- }
- })
- })
-
- describe('HLS only studio edition', function () {
-
- before(async function () {
- // Disable Web Videos
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- webVideos: {
- enabled: false
- }
- }
- }
- })
- })
-
- it('Should run a complex task on HLS only video', async function () {
- this.timeout(240_000)
- await renewVideo()
-
- await createTasks(VideoStudioCommand.getComplexTask())
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.files).to.have.lengthOf(0)
-
- await checkVideoDuration(server, videoUUID, 9)
- }
- })
- })
-
- describe('Server restart', function () {
-
- it('Should still be able to run video edition after a server restart', async function () {
- this.timeout(240_000)
-
- await renewVideo()
- await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks: VideoStudioCommand.getComplexTask() })
-
- await servers[0].kill()
- await servers[0].run()
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkVideoDuration(server, videoUUID, 9)
- }
- })
-
- it('Should have an empty persistent tmp directory', async function () {
- await checkPersistentTmpIsEmpty(servers[0])
- })
- })
-
- describe('Object storage studio edition', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
- await servers[0].run(objectStorage.getDefaultMockConfig())
-
- await servers[0].config.enableMinimumTranscoding()
- })
-
- it('Should run a complex task on a video in object storage', async function () {
- this.timeout(240_000)
- await renewVideo()
-
- const video = await servers[0].videos.get({ id: videoUUID })
- const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
-
- await createTasks(VideoStudioCommand.getComplexTask())
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- const files = getAllFiles(video)
-
- for (const f of files) {
- expect(oldFileUrls).to.not.include(f.fileUrl)
- }
-
- for (const webVideoFile of video.files) {
- expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
-
- for (const hlsFile of video.streamingPlaylists[0].files) {
- expectStartWith(hlsFile.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- }
-
- await checkVideoDuration(server, videoUUID, 9)
- }
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/users/index.ts b/server/tests/api/users/index.ts
deleted file mode 100644
index a4443a8ec..000000000
--- a/server/tests/api/users/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import './oauth'
-import './registrations`'
-import './two-factor'
-import './user-subscriptions'
-import './user-videos'
-import './users'
-import './users-multiple-servers'
-import './users-email-verification'
diff --git a/server/tests/api/users/oauth.ts b/server/tests/api/users/oauth.ts
deleted file mode 100644
index 153615875..000000000
--- a/server/tests/api/users/oauth.ts
+++ /dev/null
@@ -1,197 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { SQLCommand } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, OAuth2ErrorCode, PeerTubeProblemDocument } from '@shared/models'
-import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test oauth', function () {
- let server: PeerTubeServer
- let sqlCommand: SQLCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {
- rates_limit: {
- login: {
- max: 30
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
-
- sqlCommand = new SQLCommand(server)
- })
-
- describe('OAuth client', function () {
-
- function expectInvalidClient (body: PeerTubeProblemDocument) {
- expect(body.code).to.equal(OAuth2ErrorCode.INVALID_CLIENT)
- expect(body.error).to.contain('client is invalid')
- expect(body.type.startsWith('https://')).to.be.true
- expect(body.type).to.contain(OAuth2ErrorCode.INVALID_CLIENT)
- }
-
- it('Should create a new client')
-
- it('Should return the first client')
-
- it('Should remove the last client')
-
- it('Should not login with an invalid client id', async function () {
- const client = { id: 'client', secret: server.store.client.secret }
- const body = await server.login.login({ client, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- expectInvalidClient(body)
- })
-
- it('Should not login with an invalid client secret', async function () {
- const client = { id: server.store.client.id, secret: 'coucou' }
- const body = await server.login.login({ client, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- expectInvalidClient(body)
- })
- })
-
- describe('Login', function () {
-
- function expectInvalidCredentials (body: PeerTubeProblemDocument) {
- expect(body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
- expect(body.error).to.contain('credentials are invalid')
- expect(body.type.startsWith('https://')).to.be.true
- expect(body.type).to.contain(OAuth2ErrorCode.INVALID_GRANT)
- }
-
- it('Should not login with an invalid username', async function () {
- const user = { username: 'captain crochet', password: server.store.user.password }
- const body = await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- expectInvalidCredentials(body)
- })
-
- it('Should not login with an invalid password', async function () {
- const user = { username: server.store.user.username, password: 'mew_three' }
- const body = await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- expectInvalidCredentials(body)
- })
-
- it('Should be able to login', async function () {
- await server.login.login({ expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should be able to login with an insensitive username', async function () {
- const user = { username: 'RoOt', password: server.store.user.password }
- await server.login.login({ user, expectedStatus: HttpStatusCode.OK_200 })
-
- const user2 = { username: 'rOoT', password: server.store.user.password }
- await server.login.login({ user: user2, expectedStatus: HttpStatusCode.OK_200 })
-
- const user3 = { username: 'ROOt', password: server.store.user.password }
- await server.login.login({ user: user3, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('Logout', function () {
-
- it('Should logout (revoke token)', async function () {
- await server.login.logout({ token: server.accessToken })
- })
-
- it('Should not be able to get the user information', async function () {
- await server.users.getMyInfo({ expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not be able to upload a video', async function () {
- await server.videos.upload({ attributes: { name: 'video' }, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should be able to login again', async function () {
- const body = await server.login.login()
- server.accessToken = body.access_token
- server.refreshToken = body.refresh_token
- })
-
- it('Should be able to get my user information again', async function () {
- await server.users.getMyInfo()
- })
-
- it('Should have an expired access token', async function () {
- this.timeout(60000)
-
- await sqlCommand.setTokenField(server.accessToken, 'accessTokenExpiresAt', new Date().toISOString())
- await sqlCommand.setTokenField(server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString())
-
- await killallServers([ server ])
- await server.run()
-
- await server.users.getMyInfo({ expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not be able to refresh an access token with an expired refresh token', async function () {
- await server.login.refreshToken({ refreshToken: server.refreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should refresh the token', async function () {
- this.timeout(50000)
-
- const futureDate = new Date(new Date().getTime() + 1000 * 60).toISOString()
- await sqlCommand.setTokenField(server.accessToken, 'refreshTokenExpiresAt', futureDate)
-
- await killallServers([ server ])
- await server.run()
-
- const res = await server.login.refreshToken({ refreshToken: server.refreshToken })
- server.accessToken = res.body.access_token
- server.refreshToken = res.body.refresh_token
- })
-
- it('Should be able to get my user information again', async function () {
- await server.users.getMyInfo()
- })
- })
-
- describe('Custom token lifetime', function () {
- before(async function () {
- this.timeout(120_000)
-
- await server.kill()
- await server.run({
- oauth2: {
- token_lifetime: {
- access_token: '2 seconds',
- refresh_token: '2 seconds'
- }
- }
- })
- })
-
- it('Should have a very short access token lifetime', async function () {
- this.timeout(50000)
-
- const { access_token: accessToken } = await server.login.login()
- await server.users.getMyInfo({ token: accessToken })
-
- await wait(3000)
- await server.users.getMyInfo({ token: accessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should have a very short refresh token lifetime', async function () {
- this.timeout(50000)
-
- const { refresh_token: refreshToken } = await server.login.login()
- await server.login.refreshToken({ refreshToken })
-
- await wait(3000)
- await server.login.refreshToken({ refreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
- })
-
- after(async function () {
- await sqlCommand.cleanup()
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/users/registrations.ts b/server/tests/api/users/registrations.ts
deleted file mode 100644
index e6524f07d..000000000
--- a/server/tests/api/users/registrations.ts
+++ /dev/null
@@ -1,415 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { MockSmtpServer } from '@server/tests/shared'
-import { UserRegistrationState, UserRole } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test registrations', function () {
- let server: PeerTubeServer
-
- const emails: object[] = []
- let emailPort: number
-
- before(async function () {
- this.timeout(30000)
-
- emailPort = await MockSmtpServer.Instance.collectEmails(emails)
-
- server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(emailPort))
-
- await setAccessTokensToServers([ server ])
- await server.config.enableSignup(false)
- })
-
- describe('Direct registrations of a new user', function () {
- let user1Token: string
-
- it('Should register a new user', async function () {
- const user = { displayName: 'super user 1', username: 'user_1', password: 'my super password' }
- const channel = { name: 'my_user_1_channel', displayName: 'my channel rocks' }
-
- await server.registrations.register({ ...user, channel })
- })
-
- it('Should be able to login with this registered user', async function () {
- const user1 = { username: 'user_1', password: 'my super password' }
-
- user1Token = await server.login.getAccessToken(user1)
- })
-
- it('Should have the correct display name', async function () {
- const user = await server.users.getMyInfo({ token: user1Token })
- expect(user.account.displayName).to.equal('super user 1')
- })
-
- it('Should have the correct video quota', async function () {
- const user = await server.users.getMyInfo({ token: user1Token })
- expect(user.videoQuota).to.equal(5 * 1024 * 1024)
- })
-
- it('Should have created the channel', async function () {
- const { displayName } = await server.channels.get({ channelName: 'my_user_1_channel' })
-
- expect(displayName).to.equal('my channel rocks')
- })
-
- it('Should remove me', async function () {
- {
- const { data } = await server.users.list()
- expect(data.find(u => u.username === 'user_1')).to.not.be.undefined
- }
-
- await server.users.deleteMe({ token: user1Token })
-
- {
- const { data } = await server.users.list()
- expect(data.find(u => u.username === 'user_1')).to.be.undefined
- }
- })
- })
-
- describe('Registration requests', function () {
- let id2: number
- let id3: number
- let id4: number
-
- let user2Token: string
- let user3Token: string
-
- before(async function () {
- this.timeout(60000)
-
- await server.config.enableSignup(true)
-
- {
- const { id } = await server.registrations.requestRegistration({
- username: 'user4',
- registrationReason: 'registration reason 4'
- })
-
- id4 = id
- }
- })
-
- it('Should request a registration without a channel', async function () {
- {
- const { id } = await server.registrations.requestRegistration({
- username: 'user2',
- displayName: 'my super user 2',
- email: 'user2@example.com',
- password: 'user2password',
- registrationReason: 'registration reason 2'
- })
-
- id2 = id
- }
- })
-
- it('Should request a registration with a channel', async function () {
- const { id } = await server.registrations.requestRegistration({
- username: 'user3',
- displayName: 'my super user 3',
- channel: {
- displayName: 'my user 3 channel',
- name: 'super_user3_channel'
- },
- email: 'user3@example.com',
- password: 'user3password',
- registrationReason: 'registration reason 3'
- })
-
- id3 = id
- })
-
- it('Should list these registration requests', async function () {
- {
- const { total, data } = await server.registrations.list({ sort: '-createdAt' })
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
-
- {
- expect(data[0].id).to.equal(id3)
- expect(data[0].username).to.equal('user3')
- expect(data[0].accountDisplayName).to.equal('my super user 3')
-
- expect(data[0].channelDisplayName).to.equal('my user 3 channel')
- expect(data[0].channelHandle).to.equal('super_user3_channel')
-
- expect(data[0].createdAt).to.exist
- expect(data[0].updatedAt).to.exist
-
- expect(data[0].email).to.equal('user3@example.com')
- expect(data[0].emailVerified).to.be.null
-
- expect(data[0].moderationResponse).to.be.null
- expect(data[0].registrationReason).to.equal('registration reason 3')
- expect(data[0].state.id).to.equal(UserRegistrationState.PENDING)
- expect(data[0].state.label).to.equal('Pending')
- expect(data[0].user).to.be.null
- }
-
- {
- expect(data[1].id).to.equal(id2)
- expect(data[1].username).to.equal('user2')
- expect(data[1].accountDisplayName).to.equal('my super user 2')
-
- expect(data[1].channelDisplayName).to.be.null
- expect(data[1].channelHandle).to.be.null
-
- expect(data[1].createdAt).to.exist
- expect(data[1].updatedAt).to.exist
-
- expect(data[1].email).to.equal('user2@example.com')
- expect(data[1].emailVerified).to.be.null
-
- expect(data[1].moderationResponse).to.be.null
- expect(data[1].registrationReason).to.equal('registration reason 2')
- expect(data[1].state.id).to.equal(UserRegistrationState.PENDING)
- expect(data[1].state.label).to.equal('Pending')
- expect(data[1].user).to.be.null
- }
-
- {
- expect(data[2].username).to.equal('user4')
- }
- }
-
- {
- const { total, data } = await server.registrations.list({ count: 1, start: 1, sort: 'createdAt' })
-
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(id2)
- }
-
- {
- const { total, data } = await server.registrations.list({ search: 'user3' })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(id3)
- }
- })
-
- it('Should reject a registration request', async function () {
- await server.registrations.reject({ id: id4, moderationResponse: 'I do not want id 4 on this instance' })
- })
-
- it('Should have sent an email to the user explanining the registration has been rejected', async function () {
- this.timeout(50000)
-
- await waitJobs([ server ])
-
- const email = emails.find(e => e['to'][0]['address'] === 'user4@example.com')
- expect(email).to.exist
-
- expect(email['subject']).to.contain('been rejected')
- expect(email['text']).to.contain('been rejected')
- expect(email['text']).to.contain('I do not want id 4 on this instance')
- })
-
- it('Should accept registration requests', async function () {
- await server.registrations.accept({ id: id2, moderationResponse: 'Welcome id 2' })
- await server.registrations.accept({ id: id3, moderationResponse: 'Welcome id 3' })
- })
-
- it('Should have sent an email to the user explanining the registration has been accepted', async function () {
- this.timeout(50000)
-
- await waitJobs([ server ])
-
- {
- const email = emails.find(e => e['to'][0]['address'] === 'user2@example.com')
- expect(email).to.exist
-
- expect(email['subject']).to.contain('been accepted')
- expect(email['text']).to.contain('been accepted')
- expect(email['text']).to.contain('Welcome id 2')
- }
-
- {
- const email = emails.find(e => e['to'][0]['address'] === 'user3@example.com')
- expect(email).to.exist
-
- expect(email['subject']).to.contain('been accepted')
- expect(email['text']).to.contain('been accepted')
- expect(email['text']).to.contain('Welcome id 3')
- }
- })
-
- it('Should login with these users', async function () {
- user2Token = await server.login.getAccessToken({ username: 'user2', password: 'user2password' })
- user3Token = await server.login.getAccessToken({ username: 'user3', password: 'user3password' })
- })
-
- it('Should have created the appropriate attributes for user 2', async function () {
- const me = await server.users.getMyInfo({ token: user2Token })
-
- expect(me.username).to.equal('user2')
- expect(me.account.displayName).to.equal('my super user 2')
- expect(me.videoQuota).to.equal(5 * 1024 * 1024)
- expect(me.videoChannels[0].name).to.equal('user2_channel')
- expect(me.videoChannels[0].displayName).to.equal('Main user2 channel')
- expect(me.role.id).to.equal(UserRole.USER)
- expect(me.email).to.equal('user2@example.com')
- })
-
- it('Should have created the appropriate attributes for user 3', async function () {
- const me = await server.users.getMyInfo({ token: user3Token })
-
- expect(me.username).to.equal('user3')
- expect(me.account.displayName).to.equal('my super user 3')
- expect(me.videoQuota).to.equal(5 * 1024 * 1024)
- expect(me.videoChannels[0].name).to.equal('super_user3_channel')
- expect(me.videoChannels[0].displayName).to.equal('my user 3 channel')
- expect(me.role.id).to.equal(UserRole.USER)
- expect(me.email).to.equal('user3@example.com')
- })
-
- it('Should list these accepted/rejected registration requests', async function () {
- const { data } = await server.registrations.list({ sort: 'createdAt' })
- const { data: users } = await server.users.list()
-
- {
- expect(data[0].id).to.equal(id4)
- expect(data[0].state.id).to.equal(UserRegistrationState.REJECTED)
- expect(data[0].state.label).to.equal('Rejected')
-
- expect(data[0].moderationResponse).to.equal('I do not want id 4 on this instance')
- expect(data[0].user).to.be.null
-
- expect(users.find(u => u.username === 'user4')).to.not.exist
- }
-
- {
- expect(data[1].id).to.equal(id2)
- expect(data[1].state.id).to.equal(UserRegistrationState.ACCEPTED)
- expect(data[1].state.label).to.equal('Accepted')
-
- expect(data[1].moderationResponse).to.equal('Welcome id 2')
- expect(data[1].user).to.exist
-
- const user2 = users.find(u => u.username === 'user2')
- expect(data[1].user.id).to.equal(user2.id)
- }
-
- {
- expect(data[2].id).to.equal(id3)
- expect(data[2].state.id).to.equal(UserRegistrationState.ACCEPTED)
- expect(data[2].state.label).to.equal('Accepted')
-
- expect(data[2].moderationResponse).to.equal('Welcome id 3')
- expect(data[2].user).to.exist
-
- const user3 = users.find(u => u.username === 'user3')
- expect(data[2].user.id).to.equal(user3.id)
- }
- })
-
- it('Shoulde delete a registration', async function () {
- await server.registrations.delete({ id: id2 })
- await server.registrations.delete({ id: id3 })
-
- const { total, data } = await server.registrations.list()
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(id4)
-
- const { data: users } = await server.users.list()
-
- for (const username of [ 'user2', 'user3' ]) {
- expect(users.find(u => u.username === username)).to.exist
- }
- })
-
- it('Should be able to prevent email delivery on accept/reject', async function () {
- this.timeout(50000)
-
- let id1: number
- let id2: number
-
- {
- const { id } = await server.registrations.requestRegistration({
- username: 'user7',
- email: 'user7@example.com',
- registrationReason: 'tt'
- })
- id1 = id
- }
- {
- const { id } = await server.registrations.requestRegistration({
- username: 'user8',
- email: 'user8@example.com',
- registrationReason: 'tt'
- })
- id2 = id
- }
-
- await server.registrations.accept({ id: id1, moderationResponse: 'tt', preventEmailDelivery: true })
- await server.registrations.reject({ id: id2, moderationResponse: 'tt', preventEmailDelivery: true })
-
- await waitJobs([ server ])
-
- const filtered = emails.filter(e => {
- const address = e['to'][0]['address']
- return address === 'user7@example.com' || address === 'user8@example.com'
- })
-
- expect(filtered).to.have.lengthOf(0)
- })
-
- it('Should request a registration without a channel, that will conflict with an already existing channel', async function () {
- let id1: number
- let id2: number
-
- {
- const { id } = await server.registrations.requestRegistration({
- registrationReason: 'tt',
- username: 'user5',
- password: 'user5password',
- channel: {
- displayName: 'channel 6',
- name: 'user6_channel'
- }
- })
-
- id1 = id
- }
-
- {
- const { id } = await server.registrations.requestRegistration({
- registrationReason: 'tt',
- username: 'user6',
- password: 'user6password'
- })
-
- id2 = id
- }
-
- await server.registrations.accept({ id: id1, moderationResponse: 'tt' })
- await server.registrations.accept({ id: id2, moderationResponse: 'tt' })
-
- const user5Token = await server.login.getAccessToken('user5', 'user5password')
- const user6Token = await server.login.getAccessToken('user6', 'user6password')
-
- const user5 = await server.users.getMyInfo({ token: user5Token })
- const user6 = await server.users.getMyInfo({ token: user6Token })
-
- expect(user5.videoChannels[0].name).to.equal('user6_channel')
- expect(user6.videoChannels[0].name).to.equal('user6_channel-1')
- })
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/users/two-factor.ts b/server/tests/api/users/two-factor.ts
deleted file mode 100644
index 0dcab9e17..000000000
--- a/server/tests/api/users/two-factor.ts
+++ /dev/null
@@ -1,200 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { expectStartWith } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, TwoFactorCommand } from '@shared/server-commands'
-
-async function login (options: {
- server: PeerTubeServer
- username: string
- password: string
- otpToken?: string
- expectedStatus?: HttpStatusCode
-}) {
- const { server, username, password, otpToken, expectedStatus } = options
-
- const user = { username, password }
- const { res, body: { access_token: token } } = await server.login.loginAndGetResponse({ user, otpToken, expectedStatus })
-
- return { res, token }
-}
-
-describe('Test users', function () {
- let server: PeerTubeServer
- let otpSecret: string
- let requestToken: string
-
- const userUsername = 'user1'
- let userId: number
- let userPassword: string
- let userToken: string
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- const res = await server.users.generate(userUsername)
- userId = res.userId
- userPassword = res.password
- userToken = res.token
- })
-
- it('Should not add the header on login if two factor is not enabled', async function () {
- const { res, token } = await login({ server, username: userUsername, password: userPassword })
-
- expect(res.header['x-peertube-otp']).to.not.exist
-
- await server.users.getMyInfo({ token })
- })
-
- it('Should request two factor and get the secret and uri', async function () {
- const { otpRequest } = await server.twoFactor.request({ userId, token: userToken, currentPassword: userPassword })
-
- expect(otpRequest.requestToken).to.exist
-
- expect(otpRequest.secret).to.exist
- expect(otpRequest.secret).to.have.lengthOf(32)
-
- expect(otpRequest.uri).to.exist
- expectStartWith(otpRequest.uri, 'otpauth://')
- expect(otpRequest.uri).to.include(otpRequest.secret)
-
- requestToken = otpRequest.requestToken
- otpSecret = otpRequest.secret
- })
-
- it('Should not have two factor confirmed yet', async function () {
- const { twoFactorEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(twoFactorEnabled).to.be.false
- })
-
- it('Should confirm two factor', async function () {
- await server.twoFactor.confirmRequest({
- userId,
- token: userToken,
- otpToken: TwoFactorCommand.buildOTP({ secret: otpSecret }).generate(),
- requestToken
- })
- })
-
- it('Should not add the header on login if two factor is enabled and password is incorrect', async function () {
- const { res, token } = await login({ server, username: userUsername, password: 'fake', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- expect(res.header['x-peertube-otp']).to.not.exist
- expect(token).to.not.exist
- })
-
- it('Should add the header on login if two factor is enabled and password is correct', async function () {
- const { res, token } = await login({
- server,
- username: userUsername,
- password: userPassword,
- expectedStatus: HttpStatusCode.UNAUTHORIZED_401
- })
-
- expect(res.header['x-peertube-otp']).to.exist
- expect(token).to.not.exist
-
- await server.users.getMyInfo({ token })
- })
-
- it('Should not login with correct password and incorrect otp secret', async function () {
- const otp = TwoFactorCommand.buildOTP({ secret: 'a'.repeat(32) })
-
- const { res, token } = await login({
- server,
- username: userUsername,
- password: userPassword,
- otpToken: otp.generate(),
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- expect(res.header['x-peertube-otp']).to.not.exist
- expect(token).to.not.exist
- })
-
- it('Should not login with correct password and incorrect otp code', async function () {
- const { res, token } = await login({
- server,
- username: userUsername,
- password: userPassword,
- otpToken: '123456',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- expect(res.header['x-peertube-otp']).to.not.exist
- expect(token).to.not.exist
- })
-
- it('Should not login with incorrect password and correct otp code', async function () {
- const otpToken = TwoFactorCommand.buildOTP({ secret: otpSecret }).generate()
-
- const { res, token } = await login({
- server,
- username: userUsername,
- password: 'fake',
- otpToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- expect(res.header['x-peertube-otp']).to.not.exist
- expect(token).to.not.exist
- })
-
- it('Should correctly login with correct password and otp code', async function () {
- const otpToken = TwoFactorCommand.buildOTP({ secret: otpSecret }).generate()
-
- const { res, token } = await login({ server, username: userUsername, password: userPassword, otpToken })
-
- expect(res.header['x-peertube-otp']).to.not.exist
- expect(token).to.exist
-
- await server.users.getMyInfo({ token })
- })
-
- it('Should have two factor enabled when getting my info', async function () {
- const { twoFactorEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(twoFactorEnabled).to.be.true
- })
-
- it('Should disable two factor and be able to login without otp token', async function () {
- await server.twoFactor.disable({ userId, token: userToken, currentPassword: userPassword })
-
- const { res, token } = await login({ server, username: userUsername, password: userPassword })
- expect(res.header['x-peertube-otp']).to.not.exist
-
- await server.users.getMyInfo({ token })
- })
-
- it('Should have two factor disabled when getting my info', async function () {
- const { twoFactorEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(twoFactorEnabled).to.be.false
- })
-
- it('Should enable two factor auth without password from an admin', async function () {
- const { otpRequest } = await server.twoFactor.request({ userId })
-
- await server.twoFactor.confirmRequest({
- userId,
- otpToken: TwoFactorCommand.buildOTP({ secret: otpRequest.secret }).generate(),
- requestToken: otpRequest.requestToken
- })
-
- const { twoFactorEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(twoFactorEnabled).to.be.true
- })
-
- it('Should disable two factor auth without password from an admin', async function () {
- await server.twoFactor.disable({ userId })
-
- const { twoFactorEnabled } = await server.users.getMyInfo({ token: userToken })
- expect(twoFactorEnabled).to.be.false
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts
deleted file mode 100644
index ad2b82a4a..000000000
--- a/server/tests/api/users/user-subscriptions.ts
+++ /dev/null
@@ -1,614 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- SubscriptionsCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test users subscriptions', function () {
- let servers: PeerTubeServer[] = []
- const users: { accessToken: string }[] = []
- let video3UUID: string
-
- let command: SubscriptionsCommand
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultChannelAvatar(servers)
- await setDefaultAccountAvatar(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- for (const server of servers) {
- const user = { username: 'user' + server.serverNumber, password: 'password' }
- await server.users.create({ username: user.username, password: user.password })
-
- const accessToken = await server.login.getAccessToken(user)
- users.push({ accessToken })
-
- const videoName1 = 'video 1-' + server.serverNumber
- await server.videos.upload({ token: accessToken, attributes: { name: videoName1 } })
-
- const videoName2 = 'video 2-' + server.serverNumber
- await server.videos.upload({ token: accessToken, attributes: { name: videoName2 } })
- }
-
- await waitJobs(servers)
-
- command = servers[0].subscriptions
- })
-
- describe('Destinction between server videos and user videos', function () {
- it('Should display videos of server 2 on server 1', async function () {
- const { total } = await servers[0].videos.list()
-
- expect(total).to.equal(4)
- })
-
- it('User of server 1 should follow user of server 3 and root of server 1', async function () {
- this.timeout(60000)
-
- await command.add({ token: users[0].accessToken, targetUri: 'user3_channel@' + servers[2].host })
- await command.add({ token: users[0].accessToken, targetUri: 'root_channel@' + servers[0].host })
-
- await waitJobs(servers)
-
- const attributes = { name: 'video server 3 added after follow' }
- const { uuid } = await servers[2].videos.upload({ token: users[2].accessToken, attributes })
- video3UUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should not display videos of server 3 on server 1', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(4)
-
- for (const video of data) {
- expect(video.name).to.not.contain('1-3')
- expect(video.name).to.not.contain('2-3')
- expect(video.name).to.not.contain('video server 3 added after follow')
- }
- })
- })
-
- describe('Subscription endpoints', function () {
-
- it('Should list subscriptions', async function () {
- {
- const body = await command.list()
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await command.list({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const subscriptions = body.data
- expect(subscriptions).to.be.an('array')
- expect(subscriptions).to.have.lengthOf(2)
-
- expect(subscriptions[0].name).to.equal('user3_channel')
- expect(subscriptions[1].name).to.equal('root_channel')
- }
- })
-
- it('Should get subscription', async function () {
- {
- const videoChannel = await command.get({ token: users[0].accessToken, uri: 'user3_channel@' + servers[2].host })
-
- expect(videoChannel.name).to.equal('user3_channel')
- expect(videoChannel.host).to.equal(servers[2].host)
- expect(videoChannel.displayName).to.equal('Main user3 channel')
- expect(videoChannel.followingCount).to.equal(0)
- expect(videoChannel.followersCount).to.equal(1)
- }
-
- {
- const videoChannel = await command.get({ token: users[0].accessToken, uri: 'root_channel@' + servers[0].host })
-
- expect(videoChannel.name).to.equal('root_channel')
- expect(videoChannel.host).to.equal(servers[0].host)
- expect(videoChannel.displayName).to.equal('Main root channel')
- expect(videoChannel.followingCount).to.equal(0)
- expect(videoChannel.followersCount).to.equal(1)
- }
- })
-
- it('Should return the existing subscriptions', async function () {
- const uris = [
- 'user3_channel@' + servers[2].host,
- 'root2_channel@' + servers[0].host,
- 'root_channel@' + servers[0].host,
- 'user3_channel@' + servers[0].host
- ]
-
- const body = await command.exist({ token: users[0].accessToken, uris })
-
- expect(body['user3_channel@' + servers[2].host]).to.be.true
- expect(body['root2_channel@' + servers[0].host]).to.be.false
- expect(body['root_channel@' + servers[0].host]).to.be.true
- expect(body['user3_channel@' + servers[0].host]).to.be.false
- })
-
- it('Should search among subscriptions', async function () {
- {
- const body = await command.list({ token: users[0].accessToken, sort: '-createdAt', search: 'user3_channel' })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
- }
-
- {
- const body = await command.list({ token: users[0].accessToken, sort: '-createdAt', search: 'toto' })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
- })
-
- describe('Subscription videos', function () {
-
- it('Should list subscription videos', async function () {
- {
- const body = await servers[0].videos.listMySubscriptionVideos()
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(3)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(3)
-
- expect(videos[0].name).to.equal('video 1-3')
- expect(videos[1].name).to.equal('video 2-3')
- expect(videos[2].name).to.equal('video server 3 added after follow')
- }
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, count: 1, start: 1 })
- expect(body.total).to.equal(3)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(1)
-
- expect(videos[0].name).to.equal('video 2-3')
- }
- })
-
- it('Should upload a video by root on server 1 and see it in the subscription videos', async function () {
- this.timeout(60000)
-
- const videoName = 'video server 1 added after follow'
- await servers[0].videos.upload({ attributes: { name: videoName } })
-
- await waitJobs(servers)
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos()
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(4)
-
- expect(videos[0].name).to.equal('video 1-3')
- expect(videos[1].name).to.equal('video 2-3')
- expect(videos[2].name).to.equal('video server 3 added after follow')
- expect(videos[3].name).to.equal('video server 1 added after follow')
- }
-
- {
- const { data, total } = await servers[0].videos.list()
- expect(total).to.equal(5)
-
- for (const video of data) {
- expect(video.name).to.not.contain('1-3')
- expect(video.name).to.not.contain('2-3')
- expect(video.name).to.not.contain('video server 3 added after follow')
- }
- }
- })
-
- it('Should have server 1 following server 3 and display server 3 videos', async function () {
- this.timeout(60000)
-
- await servers[0].follows.follow({ hosts: [ servers[2].url ] })
-
- await waitJobs(servers)
-
- const { data, total } = await servers[0].videos.list()
- expect(total).to.equal(8)
-
- const names = [ '1-3', '2-3', 'video server 3 added after follow' ]
- for (const name of names) {
- const video = data.find(v => v.name.includes(name))
- expect(video).to.not.be.undefined
- }
- })
-
- it('Should remove follow server 1 -> server 3 and hide server 3 videos', async function () {
- this.timeout(60000)
-
- await servers[0].follows.unfollow({ target: servers[2] })
-
- await waitJobs(servers)
-
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(5)
-
- for (const video of data) {
- expect(video.name).to.not.contain('1-3')
- expect(video.name).to.not.contain('2-3')
- expect(video.name).to.not.contain('video server 3 added after follow')
- }
- })
-
- it('Should still list subscription videos', async function () {
- {
- const body = await servers[0].videos.listMySubscriptionVideos()
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- }
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(4)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(4)
-
- expect(videos[0].name).to.equal('video 1-3')
- expect(videos[1].name).to.equal('video 2-3')
- expect(videos[2].name).to.equal('video server 3 added after follow')
- expect(videos[3].name).to.equal('video server 1 added after follow')
- }
- })
- })
-
- describe('Existing subscription video update', function () {
-
- it('Should update a video of server 3 and see the updated video on server 1', async function () {
- this.timeout(30000)
-
- await servers[2].videos.update({ id: video3UUID, attributes: { name: 'video server 3 added after follow updated' } })
-
- await waitJobs(servers)
-
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.data[2].name).to.equal('video server 3 added after follow updated')
- })
- })
-
- describe('Subscription removal', function () {
-
- it('Should remove user of server 3 subscription', async function () {
- this.timeout(30000)
-
- await command.remove({ token: users[0].accessToken, uri: 'user3_channel@' + servers[2].host })
-
- await waitJobs(servers)
- })
-
- it('Should not display its videos anymore', async function () {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(1)
-
- expect(videos[0].name).to.equal('video server 1 added after follow')
- })
-
- it('Should remove the root subscription and not display the videos anymore', async function () {
- this.timeout(30000)
-
- await command.remove({ token: users[0].accessToken, uri: 'root_channel@' + servers[0].host })
-
- await waitJobs(servers)
-
- {
- const body = await command.list({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(0)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(0)
- }
- })
-
- it('Should correctly display public videos on server 1', async function () {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(5)
-
- for (const video of data) {
- expect(video.name).to.not.contain('1-3')
- expect(video.name).to.not.contain('2-3')
- expect(video.name).to.not.contain('video server 3 added after follow updated')
- }
- })
- })
-
- describe('Re-follow', function () {
-
- it('Should follow user of server 3 again', async function () {
- this.timeout(60000)
-
- await command.add({ token: users[0].accessToken, targetUri: 'user3_channel@' + servers[2].host })
-
- await waitJobs(servers)
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken, sort: 'createdAt' })
- expect(body.total).to.equal(3)
-
- const videos = body.data
- expect(videos).to.be.an('array')
- expect(videos).to.have.lengthOf(3)
-
- expect(videos[0].name).to.equal('video 1-3')
- expect(videos[1].name).to.equal('video 2-3')
- expect(videos[2].name).to.equal('video server 3 added after follow updated')
- }
-
- {
- const { total, data } = await servers[0].videos.list()
- expect(total).to.equal(5)
-
- for (const video of data) {
- expect(video.name).to.not.contain('1-3')
- expect(video.name).to.not.contain('2-3')
- expect(video.name).to.not.contain('video server 3 added after follow updated')
- }
- }
- })
-
- it('Should follow user channels of server 3 by root of server 3', async function () {
- this.timeout(60000)
-
- await servers[2].channels.create({ token: users[2].accessToken, attributes: { name: 'user3_channel2' } })
-
- await servers[2].subscriptions.add({ token: servers[2].accessToken, targetUri: 'user3_channel@' + servers[2].host })
- await servers[2].subscriptions.add({ token: servers[2].accessToken, targetUri: 'user3_channel2@' + servers[2].host })
-
- await waitJobs(servers)
- })
- })
-
- describe('Followers listing', function () {
-
- it('Should list user 3 followers', async function () {
- {
- const { total, data } = await servers[2].accounts.listFollowers({
- token: users[2].accessToken,
- accountName: 'user3',
- start: 0,
- count: 5,
- sort: 'createdAt'
- })
-
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[0].host)
- expect(data[0].follower.name).to.equal('user1')
-
- expect(data[1].following.host).to.equal(servers[2].host)
- expect(data[1].following.name).to.equal('user3_channel')
- expect(data[1].follower.host).to.equal(servers[2].host)
- expect(data[1].follower.name).to.equal('root')
-
- expect(data[2].following.host).to.equal(servers[2].host)
- expect(data[2].following.name).to.equal('user3_channel2')
- expect(data[2].follower.host).to.equal(servers[2].host)
- expect(data[2].follower.name).to.equal('root')
- }
-
- {
- const { total, data } = await servers[2].accounts.listFollowers({
- token: users[2].accessToken,
- accountName: 'user3',
- start: 0,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel2')
- expect(data[0].follower.host).to.equal(servers[2].host)
- expect(data[0].follower.name).to.equal('root')
- }
-
- {
- const { total, data } = await servers[2].accounts.listFollowers({
- token: users[2].accessToken,
- accountName: 'user3',
- start: 1,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[2].host)
- expect(data[0].follower.name).to.equal('root')
- }
-
- {
- const { total, data } = await servers[2].accounts.listFollowers({
- token: users[2].accessToken,
- accountName: 'user3',
- search: 'user1',
- sort: '-createdAt'
- })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[0].host)
- expect(data[0].follower.name).to.equal('user1')
- }
- })
-
- it('Should list user3_channel followers', async function () {
- {
- const { total, data } = await servers[2].channels.listFollowers({
- token: users[2].accessToken,
- channelName: 'user3_channel',
- start: 0,
- count: 5,
- sort: 'createdAt'
- })
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[0].host)
- expect(data[0].follower.name).to.equal('user1')
-
- expect(data[1].following.host).to.equal(servers[2].host)
- expect(data[1].following.name).to.equal('user3_channel')
- expect(data[1].follower.host).to.equal(servers[2].host)
- expect(data[1].follower.name).to.equal('root')
- }
-
- {
- const { total, data } = await servers[2].channels.listFollowers({
- token: users[2].accessToken,
- channelName: 'user3_channel',
- start: 0,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[2].host)
- expect(data[0].follower.name).to.equal('root')
- }
-
- {
- const { total, data } = await servers[2].channels.listFollowers({
- token: users[2].accessToken,
- channelName: 'user3_channel',
- start: 1,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[0].host)
- expect(data[0].follower.name).to.equal('user1')
- }
-
- {
- const { total, data } = await servers[2].channels.listFollowers({
- token: users[2].accessToken,
- channelName: 'user3_channel',
- search: 'user1',
- sort: '-createdAt'
- })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].following.host).to.equal(servers[2].host)
- expect(data[0].following.name).to.equal('user3_channel')
- expect(data[0].follower.host).to.equal(servers[0].host)
- expect(data[0].follower.name).to.equal('user1')
- }
- })
- })
-
- describe('Subscription videos privacy', function () {
-
- it('Should update video as internal and not see from remote server', async function () {
- this.timeout(30000)
-
- await servers[2].videos.update({ id: video3UUID, attributes: { name: 'internal', privacy: VideoPrivacy.INTERNAL } })
- await waitJobs(servers)
-
- {
- const { data } = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken })
- expect(data.find(v => v.name === 'internal')).to.not.exist
- }
- })
-
- it('Should see internal from local user', async function () {
- const { data } = await servers[2].videos.listMySubscriptionVideos({ token: servers[2].accessToken })
- expect(data.find(v => v.name === 'internal')).to.exist
- })
-
- it('Should update video as private and not see from anyone server', async function () {
- this.timeout(30000)
-
- await servers[2].videos.update({ id: video3UUID, attributes: { name: 'private', privacy: VideoPrivacy.PRIVATE } })
- await waitJobs(servers)
-
- {
- const { data } = await servers[0].videos.listMySubscriptionVideos({ token: users[0].accessToken })
- expect(data.find(v => v.name === 'private')).to.not.exist
- }
-
- {
- const { data } = await servers[2].videos.listMySubscriptionVideos({ token: servers[2].accessToken })
- expect(data.find(v => v.name === 'private')).to.not.exist
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/users/user-videos.ts b/server/tests/api/users/user-videos.ts
deleted file mode 100644
index 77226e48e..000000000
--- a/server/tests/api/users/user-videos.ts
+++ /dev/null
@@ -1,219 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test user videos', function () {
- let server: PeerTubeServer
- let videoId: number
- let videoId2: number
- let token: string
- let anotherUserToken: string
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultChannelAvatar([ server ])
- await setDefaultAccountAvatar([ server ])
-
- await server.videos.quickUpload({ name: 'root video' })
- await server.videos.quickUpload({ name: 'root video 2' })
-
- token = await server.users.generateUserAndToken('user')
- anotherUserToken = await server.users.generateUserAndToken('user2')
- })
-
- describe('List my videos', function () {
-
- it('Should list my videos', async function () {
- const { data, total } = await server.videos.listMyVideos()
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
- })
- })
-
- describe('Upload', function () {
-
- it('Should upload the video with the correct token', async function () {
- await server.videos.upload({ token })
- const { data } = await server.videos.list()
- const video = data[0]
-
- expect(video.account.name).to.equal('user')
- videoId = video.id
- })
-
- it('Should upload the video again with the correct token', async function () {
- const { id } = await server.videos.upload({ token })
- videoId2 = id
- })
- })
-
- describe('Ratings', function () {
-
- it('Should retrieve a video rating', async function () {
- await server.videos.rate({ id: videoId, token, rating: 'like' })
- const rating = await server.users.getMyRating({ token, videoId })
-
- expect(rating.videoId).to.equal(videoId)
- expect(rating.rating).to.equal('like')
- })
-
- it('Should retrieve ratings list', async function () {
- await server.videos.rate({ id: videoId, token, rating: 'like' })
-
- const body = await server.accounts.listRatings({ accountName: 'user', token })
-
- expect(body.total).to.equal(1)
- expect(body.data[0].video.id).to.equal(videoId)
- expect(body.data[0].rating).to.equal('like')
- })
-
- it('Should retrieve ratings list by rating type', async function () {
- {
- const body = await server.accounts.listRatings({ accountName: 'user', token, rating: 'like' })
- expect(body.data.length).to.equal(1)
- }
-
- {
- const body = await server.accounts.listRatings({ accountName: 'user', token, rating: 'dislike' })
- expect(body.data.length).to.equal(0)
- }
- })
- })
-
- describe('Remove video', function () {
-
- it('Should not be able to remove the video with an incorrect token', async function () {
- await server.videos.remove({ token: 'bad_token', id: videoId, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not be able to remove the video with the token of another account', async function () {
- await server.videos.remove({ token: anotherUserToken, id: videoId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should be able to remove the video with the correct token', async function () {
- await server.videos.remove({ token, id: videoId })
- await server.videos.remove({ token, id: videoId2 })
- })
- })
-
- describe('My videos & quotas', function () {
-
- it('Should be able to upload a video with a user', async function () {
- this.timeout(30000)
-
- const attributes = {
- name: 'super user video',
- fixture: 'video_short.webm'
- }
- await server.videos.upload({ token, attributes })
-
- await server.channels.create({ token, attributes: { name: 'other_channel' } })
- })
-
- it('Should have video quota updated', async function () {
- const quota = await server.users.getMyQuotaUsed({ token })
- expect(quota.videoQuotaUsed).to.equal(218910)
- expect(quota.videoQuotaUsedDaily).to.equal(218910)
-
- const { data } = await server.users.list()
- const tmpUser = data.find(u => u.username === 'user')
- expect(tmpUser.videoQuotaUsed).to.equal(218910)
- expect(tmpUser.videoQuotaUsedDaily).to.equal(218910)
- })
-
- it('Should be able to list my videos', async function () {
- const { total, data } = await server.videos.listMyVideos({ token })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const video = data[0]
- expect(video.name).to.equal('super user video')
- expect(video.thumbnailPath).to.not.be.null
- expect(video.previewPath).to.not.be.null
- })
-
- it('Should be able to filter by channel in my videos', async function () {
- const myInfo = await server.users.getMyInfo({ token })
- const mainChannel = myInfo.videoChannels.find(c => c.name !== 'other_channel')
- const otherChannel = myInfo.videoChannels.find(c => c.name === 'other_channel')
-
- {
- const { total, data } = await server.videos.listMyVideos({ token, channelId: mainChannel.id })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- const video = data[0]
- expect(video.name).to.equal('super user video')
- expect(video.thumbnailPath).to.not.be.null
- expect(video.previewPath).to.not.be.null
- }
-
- {
- const { total, data } = await server.videos.listMyVideos({ token, channelId: otherChannel.id })
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
- })
-
- it('Should be able to search in my videos', async function () {
- {
- const { total, data } = await server.videos.listMyVideos({ token, sort: '-createdAt', search: 'user video' })
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- }
-
- {
- const { total, data } = await server.videos.listMyVideos({ token, sort: '-createdAt', search: 'toto' })
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
- })
-
- it('Should disable web videos, enable HLS, and update my quota', async function () {
- this.timeout(160000)
-
- {
- const config = await server.config.getCustomConfig()
- config.transcoding.webVideos.enabled = false
- config.transcoding.hls.enabled = true
- config.transcoding.enabled = true
- await server.config.updateCustomSubConfig({ newConfig: config })
- }
-
- {
- const attributes = {
- name: 'super user video 2',
- fixture: 'video_short.webm'
- }
- await server.videos.upload({ token, attributes })
-
- await waitJobs([ server ])
- }
-
- {
- const data = await server.users.getMyQuotaUsed({ token })
- expect(data.videoQuotaUsed).to.be.greaterThan(220000)
- expect(data.videoQuotaUsedDaily).to.be.greaterThan(220000)
- }
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/users/users-email-verification.ts b/server/tests/api/users/users-email-verification.ts
deleted file mode 100644
index 909226311..000000000
--- a/server/tests/api/users/users-email-verification.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { MockSmtpServer } from '@server/tests/shared'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- ConfigCommand,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test users email verification', function () {
- let server: PeerTubeServer
- let userId: number
- let userAccessToken: string
- let verificationString: string
- let expectedEmailsLength = 0
- const user1 = {
- username: 'user_1',
- password: 'super password'
- }
- const user2 = {
- username: 'user_2',
- password: 'super password'
- }
- const emails: object[] = []
-
- before(async function () {
- this.timeout(30000)
-
- const port = await MockSmtpServer.Instance.collectEmails(emails)
- server = await createSingleServer(1, ConfigCommand.getEmailOverrideConfig(port))
-
- await setAccessTokensToServers([ server ])
- })
-
- it('Should register user and send verification email if verification required', async function () {
- this.timeout(30000)
-
- await server.config.updateExistingSubConfig({
- newConfig: {
- signup: {
- enabled: true,
- requiresApproval: false,
- requiresEmailVerification: true,
- limit: 10
- }
- }
- })
-
- await server.registrations.register(user1)
-
- await waitJobs(server)
- expectedEmailsLength++
- expect(emails).to.have.lengthOf(expectedEmailsLength)
-
- const email = emails[expectedEmailsLength - 1]
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- expect(verificationStringMatches).not.to.be.null
-
- verificationString = verificationStringMatches[1]
- expect(verificationString).to.have.length.above(2)
-
- const userIdMatches = /userId=([0-9]+)/.exec(email['text'])
- expect(userIdMatches).not.to.be.null
-
- userId = parseInt(userIdMatches[1], 10)
-
- const body = await server.users.get({ userId })
- expect(body.emailVerified).to.be.false
- })
-
- it('Should not allow login for user with unverified email', async function () {
- const { detail } = await server.login.login({ user: user1, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- expect(detail).to.contain('User email is not verified.')
- })
-
- it('Should verify the user via email and allow login', async function () {
- await server.users.verifyEmail({ userId, verificationString })
-
- const body = await server.login.login({ user: user1 })
- userAccessToken = body.access_token
-
- const user = await server.users.get({ userId })
- expect(user.emailVerified).to.be.true
- })
-
- it('Should be able to change the user email', async function () {
- let updateVerificationString: string
-
- {
- await server.users.updateMe({
- token: userAccessToken,
- email: 'updated@example.com',
- currentPassword: user1.password
- })
-
- await waitJobs(server)
- expectedEmailsLength++
- expect(emails).to.have.lengthOf(expectedEmailsLength)
-
- const email = emails[expectedEmailsLength - 1]
-
- const verificationStringMatches = /verificationString=([a-z0-9]+)/.exec(email['text'])
- updateVerificationString = verificationStringMatches[1]
- }
-
- {
- const me = await server.users.getMyInfo({ token: userAccessToken })
- expect(me.email).to.equal('user_1@example.com')
- expect(me.pendingEmail).to.equal('updated@example.com')
- }
-
- {
- await server.users.verifyEmail({ userId, verificationString: updateVerificationString, isPendingEmail: true })
-
- const me = await server.users.getMyInfo({ token: userAccessToken })
- expect(me.email).to.equal('updated@example.com')
- expect(me.pendingEmail).to.be.null
- }
- })
-
- it('Should register user not requiring email verification if setting not enabled', async function () {
- this.timeout(5000)
- await server.config.updateExistingSubConfig({
- newConfig: {
- signup: {
- requiresEmailVerification: false
- }
- }
- })
-
- await server.registrations.register(user2)
-
- await waitJobs(server)
- expect(emails).to.have.lengthOf(expectedEmailsLength)
-
- const accessToken = await server.login.getAccessToken(user2)
-
- const user = await server.users.getMyInfo({ token: accessToken })
- expect(user.emailVerified).to.be.null
- })
-
- it('Should allow login for user with unverified email when setting later enabled', async function () {
- await server.config.updateCustomSubConfig({
- newConfig: {
- signup: {
- requiresEmailVerification: true
- }
- }
- })
-
- await server.login.getAccessToken(user2)
- })
-
- after(async function () {
- MockSmtpServer.Instance.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts
deleted file mode 100644
index 3823b74ef..000000000
--- a/server/tests/api/users/users-multiple-servers.ts
+++ /dev/null
@@ -1,216 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- checkActorFilesWereRemoved,
- checkTmpIsEmpty,
- checkVideoFilesWereRemoved,
- saveVideoInServers,
- testImage
-} from '@server/tests/shared'
-import { MyUser } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test users with multiple servers', function () {
- let servers: PeerTubeServer[] = []
-
- let user: MyUser
- let userId: number
-
- let videoUUID: string
- let userAccessToken: string
- let userAvatarFilenames: string[]
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultChannelAvatar(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- // Server 1 and server 3 follow each other
- await doubleFollow(servers[0], servers[2])
- // Server 2 and server 3 follow each other
- await doubleFollow(servers[1], servers[2])
-
- // The root user of server 1 is propagated to servers 2 and 3
- await servers[0].videos.upload()
-
- {
- const username = 'user1'
- const created = await servers[0].users.create({ username })
- userId = created.id
- userAccessToken = await servers[0].login.getAccessToken(username)
- }
-
- {
- const { uuid } = await servers[0].videos.upload({ token: userAccessToken })
- videoUUID = uuid
-
- await waitJobs(servers)
-
- await saveVideoInServers(servers, videoUUID)
- }
- })
-
- it('Should be able to update my display name', async function () {
- await servers[0].users.updateMe({ displayName: 'my super display name' })
-
- user = await servers[0].users.getMyInfo()
- expect(user.account.displayName).to.equal('my super display name')
-
- await waitJobs(servers)
- })
-
- it('Should be able to update my description', async function () {
- this.timeout(10_000)
-
- await servers[0].users.updateMe({ description: 'my super description updated' })
-
- user = await servers[0].users.getMyInfo()
- expect(user.account.displayName).to.equal('my super display name')
- expect(user.account.description).to.equal('my super description updated')
-
- await waitJobs(servers)
- })
-
- it('Should be able to update my avatar', async function () {
- this.timeout(10_000)
-
- const fixture = 'avatar2.png'
-
- await servers[0].users.updateMyAvatar({ fixture })
-
- user = await servers[0].users.getMyInfo()
- userAvatarFilenames = user.account.avatars.map(({ path }) => path)
-
- for (const avatar of user.account.avatars) {
- await testImage(servers[0].url, `avatar2-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
- }
-
- await waitJobs(servers)
- })
-
- it('Should have updated my profile on other servers too', async function () {
- let createdAt: string | Date
-
- for (const server of servers) {
- const body = await server.accounts.list({ sort: '-createdAt' })
-
- const resList = body.data.find(a => a.name === 'root' && a.host === servers[0].host)
- expect(resList).not.to.be.undefined
-
- const account = await server.accounts.get({ accountName: resList.name + '@' + resList.host })
-
- if (!createdAt) createdAt = account.createdAt
-
- expect(account.name).to.equal('root')
- expect(account.host).to.equal(servers[0].host)
- expect(account.displayName).to.equal('my super display name')
- expect(account.description).to.equal('my super description updated')
- expect(createdAt).to.equal(account.createdAt)
-
- if (server.serverNumber === 1) {
- expect(account.userId).to.be.a('number')
- } else {
- expect(account.userId).to.be.undefined
- }
-
- for (const avatar of account.avatars) {
- await testImage(server.url, `avatar2-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
- }
- }
- })
-
- it('Should list account videos', async function () {
- for (const server of servers) {
- const { total, data } = await server.videos.listByAccount({ handle: 'user1@' + servers[0].host })
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
- expect(data[0].uuid).to.equal(videoUUID)
- }
- })
-
- it('Should search through account videos', async function () {
- const created = await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'Kami no chikara' } })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.listByAccount({ handle: 'user1@' + servers[0].host, search: 'Kami' })
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
- expect(data[0].uuid).to.equal(created.uuid)
- }
- })
-
- it('Should remove the user', async function () {
- this.timeout(10_000)
-
- for (const server of servers) {
- const body = await server.accounts.list({ sort: '-createdAt' })
-
- const accountDeleted = body.data.find(a => a.name === 'user1' && a.host === servers[0].host)
- expect(accountDeleted).not.to.be.undefined
-
- const { data } = await server.channels.list()
- const videoChannelDeleted = data.find(a => a.displayName === 'Main user1 channel' && a.host === servers[0].host)
- expect(videoChannelDeleted).not.to.be.undefined
- }
-
- await servers[0].users.remove({ userId })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const body = await server.accounts.list({ sort: '-createdAt' })
-
- const accountDeleted = body.data.find(a => a.name === 'user1' && a.host === servers[0].host)
- expect(accountDeleted).to.be.undefined
-
- const { data } = await server.channels.list()
- const videoChannelDeleted = data.find(a => a.name === 'Main user1 channel' && a.host === servers[0].host)
- expect(videoChannelDeleted).to.be.undefined
- }
- })
-
- it('Should not have actor files', async () => {
- for (const server of servers) {
- for (const userAvatarFilename of userAvatarFilenames) {
- await checkActorFilesWereRemoved(userAvatarFilename, server)
- }
- }
- })
-
- it('Should not have video files', async () => {
- for (const server of servers) {
- await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
- }
- })
-
- it('Should have an empty tmp directory', async function () {
- for (const server of servers) {
- await checkTmpIsEmpty(server)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
deleted file mode 100644
index 67ade1d0d..000000000
--- a/server/tests/api/users/users.ts
+++ /dev/null
@@ -1,529 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { testImageSize } from '@server/tests/shared'
-import { AbuseState, HttpStatusCode, UserAdminFlag, UserRole, VideoPlaylistType } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test users', function () {
- let server: PeerTubeServer
- let token: string
- let userToken: string
- let videoId: number
- let userId: number
- const user = {
- username: 'user_1',
- password: 'super password'
- }
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {
- rates_limit: {
- login: {
- max: 30
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ npmName: 'peertube-theme-background-red' })
- })
-
- describe('Creating a user', function () {
-
- it('Should be able to create a new user', async function () {
- await server.users.create({ ...user, videoQuota: 2 * 1024 * 1024, adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST })
- })
-
- it('Should be able to login with this user', async function () {
- userToken = await server.login.getAccessToken(user)
- })
-
- it('Should be able to get user information', async function () {
- const userMe = await server.users.getMyInfo({ token: userToken })
-
- const userGet = await server.users.get({ userId: userMe.id, withStats: true })
-
- for (const user of [ userMe, userGet ]) {
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('user_1@example.com')
- expect(user.nsfwPolicy).to.equal('display')
- expect(user.videoQuota).to.equal(2 * 1024 * 1024)
- expect(user.role.label).to.equal('User')
- expect(user.id).to.be.a('number')
- expect(user.account.displayName).to.equal('user_1')
- expect(user.account.description).to.be.null
- }
-
- expect(userMe.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST)
- expect(userGet.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST)
-
- expect(userMe.specialPlaylists).to.have.lengthOf(1)
- expect(userMe.specialPlaylists[0].type).to.equal(VideoPlaylistType.WATCH_LATER)
-
- // Check stats are included with withStats
- expect(userGet.videosCount).to.be.a('number')
- expect(userGet.videosCount).to.equal(0)
- expect(userGet.videoCommentsCount).to.be.a('number')
- expect(userGet.videoCommentsCount).to.equal(0)
- expect(userGet.abusesCount).to.be.a('number')
- expect(userGet.abusesCount).to.equal(0)
- expect(userGet.abusesAcceptedCount).to.be.a('number')
- expect(userGet.abusesAcceptedCount).to.equal(0)
- })
- })
-
- describe('Users listing', function () {
-
- it('Should list all the users', async function () {
- const { data, total } = await server.users.list()
-
- expect(total).to.equal(2)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(2)
-
- const user = data[0]
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('user_1@example.com')
- expect(user.nsfwPolicy).to.equal('display')
-
- const rootUser = data[1]
- expect(rootUser.username).to.equal('root')
- expect(rootUser.email).to.equal('admin' + server.internalServerNumber + '@example.com')
- expect(user.nsfwPolicy).to.equal('display')
-
- expect(rootUser.lastLoginDate).to.exist
- expect(user.lastLoginDate).to.exist
-
- userId = user.id
- })
-
- it('Should list only the first user by username asc', async function () {
- const { total, data } = await server.users.list({ start: 0, count: 1, sort: 'username' })
-
- expect(total).to.equal(2)
- expect(data.length).to.equal(1)
-
- const user = data[0]
- expect(user.username).to.equal('root')
- expect(user.email).to.equal('admin' + server.internalServerNumber + '@example.com')
- expect(user.role.label).to.equal('Administrator')
- expect(user.nsfwPolicy).to.equal('display')
- })
-
- it('Should list only the first user by username desc', async function () {
- const { total, data } = await server.users.list({ start: 0, count: 1, sort: '-username' })
-
- expect(total).to.equal(2)
- expect(data.length).to.equal(1)
-
- const user = data[0]
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('user_1@example.com')
- expect(user.nsfwPolicy).to.equal('display')
- })
-
- it('Should list only the second user by createdAt desc', async function () {
- const { data, total } = await server.users.list({ start: 0, count: 1, sort: '-createdAt' })
- expect(total).to.equal(2)
-
- expect(data.length).to.equal(1)
-
- const user = data[0]
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('user_1@example.com')
- expect(user.nsfwPolicy).to.equal('display')
- })
-
- it('Should list all the users by createdAt asc', async function () {
- const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt' })
-
- expect(total).to.equal(2)
- expect(data.length).to.equal(2)
-
- expect(data[0].username).to.equal('root')
- expect(data[0].email).to.equal('admin' + server.internalServerNumber + '@example.com')
- expect(data[0].nsfwPolicy).to.equal('display')
-
- expect(data[1].username).to.equal('user_1')
- expect(data[1].email).to.equal('user_1@example.com')
- expect(data[1].nsfwPolicy).to.equal('display')
- })
-
- it('Should search user by username', async function () {
- const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'oot' })
- expect(total).to.equal(1)
- expect(data.length).to.equal(1)
- expect(data[0].username).to.equal('root')
- })
-
- it('Should search user by email', async function () {
- {
- const { total, data } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'r_1@exam' })
- expect(total).to.equal(1)
- expect(data.length).to.equal(1)
- expect(data[0].username).to.equal('user_1')
- expect(data[0].email).to.equal('user_1@example.com')
- }
-
- {
- const { total, data } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', search: 'example' })
- expect(total).to.equal(2)
- expect(data.length).to.equal(2)
- expect(data[0].username).to.equal('root')
- expect(data[1].username).to.equal('user_1')
- }
- })
- })
-
- describe('Update my account', function () {
-
- it('Should update my password', async function () {
- await server.users.updateMe({
- token: userToken,
- currentPassword: 'super password',
- password: 'new password'
- })
- user.password = 'new password'
-
- await server.login.login({ user })
- })
-
- it('Should be able to change the NSFW display attribute', async function () {
- await server.users.updateMe({
- token: userToken,
- nsfwPolicy: 'do_not_list'
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('user_1@example.com')
- expect(user.nsfwPolicy).to.equal('do_not_list')
- expect(user.videoQuota).to.equal(2 * 1024 * 1024)
- expect(user.id).to.be.a('number')
- expect(user.account.displayName).to.equal('user_1')
- expect(user.account.description).to.be.null
- })
-
- it('Should be able to change the autoPlayVideo attribute', async function () {
- await server.users.updateMe({
- token: userToken,
- autoPlayVideo: false
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.autoPlayVideo).to.be.false
- })
-
- it('Should be able to change the autoPlayNextVideo attribute', async function () {
- await server.users.updateMe({
- token: userToken,
- autoPlayNextVideo: true
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.autoPlayNextVideo).to.be.true
- })
-
- it('Should be able to change the p2p attribute', async function () {
- await server.users.updateMe({
- token: userToken,
- p2pEnabled: true
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.p2pEnabled).to.be.true
- })
-
- it('Should be able to change the email attribute', async function () {
- await server.users.updateMe({
- token: userToken,
- currentPassword: 'new password',
- email: 'updated@example.com'
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('updated@example.com')
- expect(user.nsfwPolicy).to.equal('do_not_list')
- expect(user.videoQuota).to.equal(2 * 1024 * 1024)
- expect(user.id).to.be.a('number')
- expect(user.account.displayName).to.equal('user_1')
- expect(user.account.description).to.be.null
- })
-
- it('Should be able to update my avatar with a gif', async function () {
- const fixture = 'avatar.gif'
-
- await server.users.updateMyAvatar({ token: userToken, fixture })
-
- const user = await server.users.getMyInfo({ token: userToken })
- for (const avatar of user.account.avatars) {
- await testImageSize(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.gif')
- }
- })
-
- it('Should be able to update my avatar with a gif, and then a png', async function () {
- for (const extension of [ '.png', '.gif' ]) {
- const fixture = 'avatar' + extension
-
- await server.users.updateMyAvatar({ token: userToken, fixture })
-
- const user = await server.users.getMyInfo({ token: userToken })
- for (const avatar of user.account.avatars) {
- await testImageSize(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, extension)
- }
- }
- })
-
- it('Should be able to update my display name', async function () {
- await server.users.updateMe({ token: userToken, displayName: 'new display name' })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('updated@example.com')
- expect(user.nsfwPolicy).to.equal('do_not_list')
- expect(user.videoQuota).to.equal(2 * 1024 * 1024)
- expect(user.id).to.be.a('number')
- expect(user.account.displayName).to.equal('new display name')
- expect(user.account.description).to.be.null
- })
-
- it('Should be able to update my description', async function () {
- await server.users.updateMe({ token: userToken, description: 'my super description updated' })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('updated@example.com')
- expect(user.nsfwPolicy).to.equal('do_not_list')
- expect(user.videoQuota).to.equal(2 * 1024 * 1024)
- expect(user.id).to.be.a('number')
- expect(user.account.displayName).to.equal('new display name')
- expect(user.account.description).to.equal('my super description updated')
- expect(user.noWelcomeModal).to.be.false
- expect(user.noInstanceConfigWarningModal).to.be.false
- expect(user.noAccountSetupWarningModal).to.be.false
- })
-
- it('Should be able to update my theme', async function () {
- for (const theme of [ 'background-red', 'default', 'instance-default' ]) {
- await server.users.updateMe({ token: userToken, theme })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.theme).to.equal(theme)
- }
- })
-
- it('Should be able to update my modal preferences', async function () {
- await server.users.updateMe({
- token: userToken,
- noInstanceConfigWarningModal: true,
- noWelcomeModal: true,
- noAccountSetupWarningModal: true
- })
-
- const user = await server.users.getMyInfo({ token: userToken })
- expect(user.noWelcomeModal).to.be.true
- expect(user.noInstanceConfigWarningModal).to.be.true
- expect(user.noAccountSetupWarningModal).to.be.true
- })
- })
-
- describe('Updating another user', function () {
-
- it('Should be able to update another user', async function () {
- await server.users.update({
- userId,
- token,
- email: 'updated2@example.com',
- emailVerified: true,
- videoQuota: 42,
- role: UserRole.MODERATOR,
- adminFlags: UserAdminFlag.NONE,
- pluginAuth: 'toto'
- })
-
- const user = await server.users.get({ token, userId })
-
- expect(user.username).to.equal('user_1')
- expect(user.email).to.equal('updated2@example.com')
- expect(user.emailVerified).to.be.true
- expect(user.nsfwPolicy).to.equal('do_not_list')
- expect(user.videoQuota).to.equal(42)
- expect(user.role.label).to.equal('Moderator')
- expect(user.id).to.be.a('number')
- expect(user.adminFlags).to.equal(UserAdminFlag.NONE)
- expect(user.pluginAuth).to.equal('toto')
- })
-
- it('Should reset the auth plugin', async function () {
- await server.users.update({ userId, token, pluginAuth: null })
-
- const user = await server.users.get({ token, userId })
- expect(user.pluginAuth).to.be.null
- })
-
- it('Should have removed the user token', async function () {
- await server.users.getMyQuotaUsed({ token: userToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
-
- userToken = await server.login.getAccessToken(user)
- })
-
- it('Should be able to update another user password', async function () {
- await server.users.update({ userId, token, password: 'password updated' })
-
- await server.users.getMyQuotaUsed({ token: userToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
-
- await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- user.password = 'password updated'
- userToken = await server.login.getAccessToken(user)
- })
- })
-
- describe('Remove a user', function () {
-
- before(async function () {
- await server.users.update({
- userId,
- token,
- videoQuota: 2 * 1024 * 1024
- })
-
- await server.videos.quickUpload({ name: 'user video', token: userToken, fixture: 'video_short.webm' })
- await server.videos.quickUpload({ name: 'root video' })
-
- const { total } = await server.videos.list()
- expect(total).to.equal(2)
- })
-
- it('Should be able to remove this user', async function () {
- await server.users.remove({ userId, token })
- })
-
- it('Should not be able to login with this user', async function () {
- await server.login.login({ user, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not have videos of this user', async function () {
- const { data, total } = await server.videos.list()
- expect(total).to.equal(1)
-
- const video = data[0]
- expect(video.account.name).to.equal('root')
- })
- })
-
- describe('User blocking', function () {
- let user16Id: number
- let user16AccessToken: string
-
- const user16 = {
- username: 'user_16',
- password: 'my super password'
- }
-
- it('Should block a user', async function () {
- const user = await server.users.create({ ...user16 })
- user16Id = user.id
-
- user16AccessToken = await server.login.getAccessToken(user16)
-
- await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.OK_200 })
- await server.users.banUser({ userId: user16Id })
-
- await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await server.login.login({ user: user16, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should search user by banned status', async function () {
- {
- const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', blocked: true })
- expect(total).to.equal(1)
- expect(data.length).to.equal(1)
-
- expect(data[0].username).to.equal(user16.username)
- }
-
- {
- const { data, total } = await server.users.list({ start: 0, count: 2, sort: 'createdAt', blocked: false })
- expect(total).to.equal(1)
- expect(data.length).to.equal(1)
-
- expect(data[0].username).to.not.equal(user16.username)
- }
- })
-
- it('Should unblock a user', async function () {
- await server.users.unbanUser({ userId: user16Id })
- user16AccessToken = await server.login.getAccessToken(user16)
- await server.users.getMyInfo({ token: user16AccessToken, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('User stats', function () {
- let user17Id: number
- let user17AccessToken: string
-
- it('Should report correct initial statistics about a user', async function () {
- const user17 = {
- username: 'user_17',
- password: 'my super password'
- }
- const created = await server.users.create({ ...user17 })
-
- user17Id = created.id
- user17AccessToken = await server.login.getAccessToken(user17)
-
- const user = await server.users.get({ userId: user17Id, withStats: true })
- expect(user.videosCount).to.equal(0)
- expect(user.videoCommentsCount).to.equal(0)
- expect(user.abusesCount).to.equal(0)
- expect(user.abusesCreatedCount).to.equal(0)
- expect(user.abusesAcceptedCount).to.equal(0)
- })
-
- it('Should report correct videos count', async function () {
- const attributes = { name: 'video to test user stats' }
- await server.videos.upload({ token: user17AccessToken, attributes })
-
- const { data } = await server.videos.list()
- videoId = data.find(video => video.name === attributes.name).id
-
- const user = await server.users.get({ userId: user17Id, withStats: true })
- expect(user.videosCount).to.equal(1)
- })
-
- it('Should report correct video comments for user', async function () {
- const text = 'super comment'
- await server.comments.createThread({ token: user17AccessToken, videoId, text })
-
- const user = await server.users.get({ userId: user17Id, withStats: true })
- expect(user.videoCommentsCount).to.equal(1)
- })
-
- it('Should report correct abuses counts', async function () {
- const reason = 'my super bad reason'
- await server.abuses.report({ token: user17AccessToken, videoId, reason })
-
- const body1 = await server.abuses.getAdminList()
- const abuseId = body1.data[0].id
-
- const user2 = await server.users.get({ userId: user17Id, withStats: true })
- expect(user2.abusesCount).to.equal(1) // number of incriminations
- expect(user2.abusesCreatedCount).to.equal(1) // number of reports created
-
- await server.abuses.update({ abuseId, body: { state: AbuseState.ACCEPTED } })
-
- const user3 = await server.users.get({ userId: user17Id, withStats: true })
- expect(user3.abusesAcceptedCount).to.equal(1) // number of reports created accepted
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/channel-import-videos.ts b/server/tests/api/videos/channel-import-videos.ts
deleted file mode 100644
index a66f88a0e..000000000
--- a/server/tests/api/videos/channel-import-videos.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { areHttpImportTestsDisabled } from '@shared/core-utils'
-import {
- createSingleServer,
- getServerImportConfig,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test videos import in a channel', function () {
- if (areHttpImportTestsDisabled()) return
-
- function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
-
- describe('Import using ' + mode, function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1, getServerImportConfig(mode))
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableChannelSync()
- })
-
- it('Should import a whole channel without specifying the sync id', async function () {
- this.timeout(240_000)
-
- await server.channels.importVideos({ channelName: server.store.channel.name, externalChannelUrl: FIXTURE_URLS.youtubeChannel })
- await waitJobs(server)
-
- const videos = await server.videos.listByChannel({ handle: server.store.channel.name })
- expect(videos.total).to.equal(2)
- })
-
- it('These imports should not have a sync id', async function () {
- const { total, data } = await server.imports.getMyVideoImports()
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const videoImport of data) {
- expect(videoImport.videoChannelSync).to.not.exist
- }
- })
-
- it('Should import a whole channel and specifying the sync id', async function () {
- this.timeout(240_000)
-
- {
- server.store.channel.name = 'channel2'
- const { id } = await server.channels.create({ attributes: { name: server.store.channel.name } })
- server.store.channel.id = id
- }
-
- {
- const attributes = {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: server.store.channel.id
- }
-
- const { videoChannelSync } = await server.channelSyncs.create({ attributes })
- server.store.videoChannelSync = videoChannelSync
-
- await waitJobs(server)
- }
-
- await server.channels.importVideos({
- channelName: server.store.channel.name,
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelSyncId: server.store.videoChannelSync.id
- })
-
- await waitJobs(server)
- })
-
- it('These imports should have a sync id', async function () {
- const { total, data } = await server.imports.getMyVideoImports()
-
- expect(total).to.equal(4)
- expect(data).to.have.lengthOf(4)
-
- const importsWithSyncId = data.filter(i => !!i.videoChannelSync)
- expect(importsWithSyncId).to.have.lengthOf(2)
-
- for (const videoImport of importsWithSyncId) {
- expect(videoImport.videoChannelSync).to.exist
- expect(videoImport.videoChannelSync.id).to.equal(server.store.videoChannelSync.id)
- }
- })
-
- it('Should be able to filter imports by this sync id', async function () {
- const { total, data } = await server.imports.getMyVideoImports({ videoChannelSyncId: server.store.videoChannelSync.id })
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- for (const videoImport of data) {
- expect(videoImport.videoChannelSync).to.exist
- expect(videoImport.videoChannelSync.id).to.equal(server.store.videoChannelSync.id)
- }
- })
-
- it('Should limit max amount of videos synced on full sync', async function () {
- this.timeout(240_000)
-
- await server.kill()
- await server.run({
- import: {
- video_channel_synchronization: {
- full_sync_videos_limit: 1
- }
- }
- })
-
- const { id } = await server.channels.create({ attributes: { name: 'channel3' } })
- const channel3Id = id
-
- const { videoChannelSync } = await server.channelSyncs.create({
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: channel3Id
- }
- })
- const syncId = videoChannelSync.id
-
- await waitJobs(server)
-
- await server.channels.importVideos({
- channelName: 'channel3',
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelSyncId: syncId
- })
-
- await waitJobs(server)
-
- const { total, data } = await server.videos.listByChannel({ handle: 'channel3' })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- })
-
- after(async function () {
- await server?.kill()
- })
- })
- }
-
- runSuite('yt-dlp')
-
- // FIXME: With recent changes on youtube, youtube-dl doesn't fetch live replays which means the test suite fails
- // runSuite('youtube-dl')
-})
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts
deleted file mode 100644
index 01d0c5852..000000000
--- a/server/tests/api/videos/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import './multiple-servers'
-import './resumable-upload'
-import './single-server'
-import './video-captions'
-import './video-change-ownership'
-import './video-channels'
-import './channel-import-videos'
-import './video-channel-syncs'
-import './video-comments'
-import './video-description'
-import './video-files'
-import './video-imports'
-import './video-nsfw'
-import './video-playlists'
-import './video-playlist-thumbnails'
-import './video-source'
-import './video-privacy'
-import './video-schedule-update'
-import './videos-common-filters'
-import './videos-history'
-import './videos-overview'
-import './video-static-file-privacy'
-import './video-storyboard'
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
deleted file mode 100644
index e9aa0e3a1..000000000
--- a/server/tests/api/videos/multiple-servers.ts
+++ /dev/null
@@ -1,1099 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import request from 'supertest'
-import {
- checkTmpIsEmpty,
- checkVideoFilesWereRemoved,
- checkWebTorrentWorks,
- completeVideoCheck,
- dateIsValid,
- saveVideoInServers,
- testImageGeneratedByFFmpeg
-} from '@server/tests/shared'
-import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
-import { HttpStatusCode, VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test multiple servers', function () {
- let servers: PeerTubeServer[] = []
- const toRemove = []
- let videoUUID = ''
- let videoChannelId: number
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- {
- const videoChannel = {
- name: 'super_channel_name',
- displayName: 'my channel',
- description: 'super channel'
- }
- await servers[0].channels.create({ attributes: videoChannel })
- await setDefaultChannelAvatar(servers[0], videoChannel.name)
- await setDefaultAccountAvatar(servers)
-
- const { data } = await servers[0].channels.list({ start: 0, count: 1 })
- videoChannelId = data[0].id
- }
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- // Server 1 and server 3 follow each other
- await doubleFollow(servers[0], servers[2])
- // Server 2 and server 3 follow each other
- await doubleFollow(servers[1], servers[2])
- })
-
- it('Should not have videos for all servers', async function () {
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data).to.be.an('array')
- expect(data.length).to.equal(0)
- }
- })
-
- describe('Should upload the video and propagate on each server', function () {
-
- it('Should upload the video on server 1 and propagate on each server', async function () {
- this.timeout(60000)
-
- const attributes = {
- name: 'my super name for server 1',
- category: 5,
- licence: 4,
- language: 'ja',
- nsfw: true,
- description: 'my super description for server 1',
- support: 'my super support text for server 1',
- originallyPublishedAt: '2019-02-10T13:38:14.449Z',
- tags: [ 'tag1p1', 'tag2p1' ],
- channelId: videoChannelId,
- fixture: 'video_short1.webm'
- }
- await servers[0].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- // All servers should have this video
- let publishedAt: string = null
- for (const server of servers) {
- const isLocal = server.port === servers[0].port
- const checkAttributes = {
- name: 'my super name for server 1',
- category: 5,
- licence: 4,
- language: 'ja',
- nsfw: true,
- description: 'my super description for server 1',
- support: 'my super support text for server 1',
- originallyPublishedAt: '2019-02-10T13:38:14.449Z',
- account: {
- name: 'root',
- host: servers[0].host
- },
- isLocal,
- publishedAt,
- duration: 10,
- tags: [ 'tag1p1', 'tag2p1' ],
- privacy: VideoPrivacy.PUBLIC,
- commentsEnabled: true,
- downloadEnabled: true,
- channel: {
- displayName: 'my channel',
- name: 'super_channel_name',
- description: 'super channel',
- isLocal
- },
- fixture: 'video_short1.webm',
- files: [
- {
- resolution: 720,
- size: 572456
- }
- ]
- }
-
- const { data } = await server.videos.list()
- expect(data).to.be.an('array')
- expect(data.length).to.equal(1)
- const video = data[0]
-
- await completeVideoCheck({ server, originServer: servers[0], videoUUID: video.uuid, attributes: checkAttributes })
- publishedAt = video.publishedAt as string
-
- expect(video.channel.avatars).to.have.lengthOf(2)
- expect(video.account.avatars).to.have.lengthOf(2)
-
- for (const image of [ ...video.channel.avatars, ...video.account.avatars ]) {
- expect(image.createdAt).to.exist
- expect(image.updatedAt).to.exist
- expect(image.width).to.be.above(20).and.below(1000)
- expect(image.path).to.exist
-
- await makeGetRequest({
- url: server.url,
- path: image.path,
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- }
- })
-
- it('Should upload the video on server 2 and propagate on each server', async function () {
- this.timeout(240000)
-
- const user = {
- username: 'user1',
- password: 'super_password'
- }
- await servers[1].users.create({ username: user.username, password: user.password })
- const userAccessToken = await servers[1].login.getAccessToken(user)
-
- const attributes = {
- name: 'my super name for server 2',
- category: 4,
- licence: 3,
- language: 'de',
- nsfw: true,
- description: 'my super description for server 2',
- support: 'my super support text for server 2',
- tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
- fixture: 'video_short2.webm',
- thumbnailfile: 'custom-thumbnail.jpg',
- previewfile: 'custom-preview.jpg'
- }
- await servers[1].videos.upload({ token: userAccessToken, attributes, mode: 'resumable' })
-
- // Transcoding
- await waitJobs(servers)
-
- // All servers should have this video
- for (const server of servers) {
- const isLocal = server.url === servers[1].url
- const checkAttributes = {
- name: 'my super name for server 2',
- category: 4,
- licence: 3,
- language: 'de',
- nsfw: true,
- description: 'my super description for server 2',
- support: 'my super support text for server 2',
- account: {
- name: 'user1',
- host: servers[1].host
- },
- isLocal,
- commentsEnabled: true,
- downloadEnabled: true,
- duration: 5,
- tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
- privacy: VideoPrivacy.PUBLIC,
- channel: {
- displayName: 'Main user1 channel',
- name: 'user1_channel',
- description: 'super channel',
- isLocal
- },
- fixture: 'video_short2.webm',
- files: [
- {
- resolution: 240,
- size: 270000
- },
- {
- resolution: 360,
- size: 359000
- },
- {
- resolution: 480,
- size: 465000
- },
- {
- resolution: 720,
- size: 750000
- }
- ],
- thumbnailfile: 'custom-thumbnail',
- previewfile: 'custom-preview'
- }
-
- const { data } = await server.videos.list()
- expect(data).to.be.an('array')
- expect(data.length).to.equal(2)
- const video = data[1]
-
- await completeVideoCheck({ server, originServer: servers[1], videoUUID: video.uuid, attributes: checkAttributes })
- }
- })
-
- it('Should upload two videos on server 3 and propagate on each server', async function () {
- this.timeout(45000)
-
- {
- const attributes = {
- name: 'my super name for server 3',
- category: 6,
- licence: 5,
- language: 'de',
- nsfw: true,
- description: 'my super description for server 3',
- support: 'my super support text for server 3',
- tags: [ 'tag1p3' ],
- fixture: 'video_short3.webm'
- }
- await servers[2].videos.upload({ attributes })
- }
-
- {
- const attributes = {
- name: 'my super name for server 3-2',
- category: 7,
- licence: 6,
- language: 'ko',
- nsfw: false,
- description: 'my super description for server 3-2',
- support: 'my super support text for server 3-2',
- tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
- fixture: 'video_short.webm'
- }
- await servers[2].videos.upload({ attributes })
- }
-
- await waitJobs(servers)
-
- // All servers should have this video
- for (const server of servers) {
- const isLocal = server.url === servers[2].url
- const { data } = await server.videos.list()
-
- expect(data).to.be.an('array')
- expect(data.length).to.equal(4)
-
- // We not sure about the order of the two last uploads
- let video1 = null
- let video2 = null
- if (data[2].name === 'my super name for server 3') {
- video1 = data[2]
- video2 = data[3]
- } else {
- video1 = data[3]
- video2 = data[2]
- }
-
- const checkAttributesVideo1 = {
- name: 'my super name for server 3',
- category: 6,
- licence: 5,
- language: 'de',
- nsfw: true,
- description: 'my super description for server 3',
- support: 'my super support text for server 3',
- account: {
- name: 'root',
- host: servers[2].host
- },
- isLocal,
- duration: 5,
- commentsEnabled: true,
- downloadEnabled: true,
- tags: [ 'tag1p3' ],
- privacy: VideoPrivacy.PUBLIC,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal
- },
- fixture: 'video_short3.webm',
- files: [
- {
- resolution: 720,
- size: 292677
- }
- ]
- }
- await completeVideoCheck({ server, originServer: servers[2], videoUUID: video1.uuid, attributes: checkAttributesVideo1 })
-
- const checkAttributesVideo2 = {
- name: 'my super name for server 3-2',
- category: 7,
- licence: 6,
- language: 'ko',
- nsfw: false,
- description: 'my super description for server 3-2',
- support: 'my super support text for server 3-2',
- account: {
- name: 'root',
- host: servers[2].host
- },
- commentsEnabled: true,
- downloadEnabled: true,
- isLocal,
- duration: 5,
- tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
- privacy: VideoPrivacy.PUBLIC,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal
- },
- fixture: 'video_short.webm',
- files: [
- {
- resolution: 720,
- size: 218910
- }
- ]
- }
- await completeVideoCheck({ server, originServer: servers[2], videoUUID: video2.uuid, attributes: checkAttributesVideo2 })
- }
- })
- })
-
- describe('It should list local videos', function () {
- it('Should list only local videos on server 1', async function () {
- const { data, total } = await servers[0].videos.list({ isLocal: true })
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(1)
- expect(data[0].name).to.equal('my super name for server 1')
- })
-
- it('Should list only local videos on server 2', async function () {
- const { data, total } = await servers[1].videos.list({ isLocal: true })
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(1)
- expect(data[0].name).to.equal('my super name for server 2')
- })
-
- it('Should list only local videos on server 3', async function () {
- const { data, total } = await servers[2].videos.list({ isLocal: true })
-
- expect(total).to.equal(2)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(2)
- expect(data[0].name).to.equal('my super name for server 3')
- expect(data[1].name).to.equal('my super name for server 3-2')
- })
- })
-
- describe('Should seed the uploaded video', function () {
-
- it('Should add the file 1 by asking server 3', async function () {
- this.retries(2)
- this.timeout(30000)
-
- const { data } = await servers[2].videos.list()
-
- const video = data[0]
- toRemove.push(data[2])
- toRemove.push(data[3])
-
- const videoDetails = await servers[2].videos.get({ id: video.id })
-
- await checkWebTorrentWorks(videoDetails.files[0].magnetUri)
- })
-
- it('Should add the file 2 by asking server 1', async function () {
- this.retries(2)
- this.timeout(30000)
-
- const { data } = await servers[0].videos.list()
-
- const video = data[1]
- const videoDetails = await servers[0].videos.get({ id: video.id })
-
- await checkWebTorrentWorks(videoDetails.files[0].magnetUri)
- })
-
- it('Should add the file 3 by asking server 2', async function () {
- this.retries(2)
- this.timeout(30000)
-
- const { data } = await servers[1].videos.list()
-
- const video = data[2]
- const videoDetails = await servers[1].videos.get({ id: video.id })
-
- await checkWebTorrentWorks(videoDetails.files[0].magnetUri)
- })
-
- it('Should add the file 3-2 by asking server 1', async function () {
- this.retries(2)
- this.timeout(30000)
-
- const { data } = await servers[0].videos.list()
-
- const video = data[3]
- const videoDetails = await servers[0].videos.get({ id: video.id })
-
- await checkWebTorrentWorks(videoDetails.files[0].magnetUri)
- })
-
- it('Should add the file 2 in 360p by asking server 1', async function () {
- this.retries(2)
- this.timeout(30000)
-
- const { data } = await servers[0].videos.list()
-
- const video = data.find(v => v.name === 'my super name for server 2')
- const videoDetails = await servers[0].videos.get({ id: video.id })
-
- const file = videoDetails.files.find(f => f.resolution.id === 360)
- expect(file).not.to.be.undefined
-
- await checkWebTorrentWorks(file.magnetUri)
- })
- })
-
- describe('Should update video views, likes and dislikes', function () {
- let localVideosServer3 = []
- let remoteVideosServer1 = []
- let remoteVideosServer2 = []
- let remoteVideosServer3 = []
-
- before(async function () {
- {
- const { data } = await servers[0].videos.list()
- remoteVideosServer1 = data.filter(video => video.isLocal === false).map(video => video.uuid)
- }
-
- {
- const { data } = await servers[1].videos.list()
- remoteVideosServer2 = data.filter(video => video.isLocal === false).map(video => video.uuid)
- }
-
- {
- const { data } = await servers[2].videos.list()
- localVideosServer3 = data.filter(video => video.isLocal === true).map(video => video.uuid)
- remoteVideosServer3 = data.filter(video => video.isLocal === false).map(video => video.uuid)
- }
- })
-
- it('Should view multiple videos on owned servers', async function () {
- this.timeout(30000)
-
- await servers[2].views.simulateView({ id: localVideosServer3[0] })
- await wait(1000)
-
- await servers[2].views.simulateView({ id: localVideosServer3[0] })
- await servers[2].views.simulateView({ id: localVideosServer3[1] })
-
- await wait(1000)
-
- await servers[2].views.simulateView({ id: localVideosServer3[0] })
- await servers[2].views.simulateView({ id: localVideosServer3[0] })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } })
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const video0 = data.find(v => v.uuid === localVideosServer3[0])
- const video1 = data.find(v => v.uuid === localVideosServer3[1])
-
- expect(video0.views).to.equal(3)
- expect(video1.views).to.equal(1)
- }
- })
-
- it('Should view multiple videos on each servers', async function () {
- this.timeout(45000)
-
- const tasks: Promise[] = []
- tasks.push(servers[0].views.simulateView({ id: remoteVideosServer1[0] }))
- tasks.push(servers[1].views.simulateView({ id: remoteVideosServer2[0] }))
- tasks.push(servers[1].views.simulateView({ id: remoteVideosServer2[0] }))
- tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[0] }))
- tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] }))
- tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] }))
- tasks.push(servers[2].views.simulateView({ id: remoteVideosServer3[1] }))
- tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] }))
- tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] }))
- tasks.push(servers[2].views.simulateView({ id: localVideosServer3[1] }))
-
- await Promise.all(tasks)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } })
- }
-
- await waitJobs(servers)
-
- let baseVideos = null
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- // Initialize base videos for future comparisons
- if (baseVideos === null) {
- baseVideos = data
- continue
- }
-
- for (const baseVideo of baseVideos) {
- const sameVideo = data.find(video => video.name === baseVideo.name)
- expect(baseVideo.views).to.equal(sameVideo.views)
- }
- }
- })
-
- it('Should like and dislikes videos on different services', async function () {
- this.timeout(50000)
-
- await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
- await wait(500)
- await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'dislike' })
- await wait(500)
- await servers[0].videos.rate({ id: remoteVideosServer1[0], rating: 'like' })
- await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'like' })
- await wait(500)
- await servers[2].videos.rate({ id: localVideosServer3[1], rating: 'dislike' })
- await servers[2].videos.rate({ id: remoteVideosServer3[1], rating: 'dislike' })
- await wait(500)
- await servers[2].videos.rate({ id: remoteVideosServer3[0], rating: 'like' })
-
- await waitJobs(servers)
- await wait(5000)
- await waitJobs(servers)
-
- let baseVideos = null
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- // Initialize base videos for future comparisons
- if (baseVideos === null) {
- baseVideos = data
- continue
- }
-
- for (const baseVideo of baseVideos) {
- const sameVideo = data.find(video => video.name === baseVideo.name)
- expect(baseVideo.likes).to.equal(sameVideo.likes, `Likes of ${sameVideo.uuid} do not correspond`)
- expect(baseVideo.dislikes).to.equal(sameVideo.dislikes, `Dislikes of ${sameVideo.uuid} do not correspond`)
- }
- }
- })
- })
-
- describe('Should manipulate these videos', function () {
- let updatedAtMin: Date
-
- it('Should update video 3', async function () {
- this.timeout(30000)
-
- const attributes = {
- name: 'my super video updated',
- category: 10,
- licence: 7,
- language: 'fr',
- nsfw: true,
- description: 'my super description updated',
- support: 'my super support text updated',
- tags: [ 'tag_up_1', 'tag_up_2' ],
- thumbnailfile: 'custom-thumbnail.jpg',
- originallyPublishedAt: '2019-02-11T13:38:14.449Z',
- previewfile: 'custom-preview.jpg'
- }
-
- updatedAtMin = new Date()
- await servers[2].videos.update({ id: toRemove[0].id, attributes })
-
- await waitJobs(servers)
- })
-
- it('Should have the video 3 updated on each server', async function () {
- this.timeout(30000)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const videoUpdated = data.find(video => video.name === 'my super video updated')
- expect(!!videoUpdated).to.be.true
-
- expect(new Date(videoUpdated.updatedAt)).to.be.greaterThan(updatedAtMin)
-
- const isLocal = server.url === servers[2].url
- const checkAttributes = {
- name: 'my super video updated',
- category: 10,
- licence: 7,
- language: 'fr',
- nsfw: true,
- description: 'my super description updated',
- support: 'my super support text updated',
- originallyPublishedAt: '2019-02-11T13:38:14.449Z',
- account: {
- name: 'root',
- host: servers[2].host
- },
- isLocal,
- duration: 5,
- commentsEnabled: true,
- downloadEnabled: true,
- tags: [ 'tag_up_1', 'tag_up_2' ],
- privacy: VideoPrivacy.PUBLIC,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal
- },
- fixture: 'video_short3.webm',
- files: [
- {
- resolution: 720,
- size: 292677
- }
- ],
- thumbnailfile: 'custom-thumbnail',
- previewfile: 'custom-preview'
- }
- await completeVideoCheck({ server, originServer: servers[2], videoUUID: videoUpdated.uuid, attributes: checkAttributes })
- }
- })
-
- it('Should only update thumbnail and update updatedAt attribute', async function () {
- this.timeout(30000)
-
- const attributes = {
- thumbnailfile: 'custom-thumbnail.jpg'
- }
-
- updatedAtMin = new Date()
- await servers[2].videos.update({ id: toRemove[0].id, attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- const videoUpdated = data.find(video => video.name === 'my super video updated')
- expect(new Date(videoUpdated.updatedAt)).to.be.greaterThan(updatedAtMin)
- }
- })
-
- it('Should remove the videos 3 and 3-2 by asking server 3 and correctly delete files', async function () {
- this.timeout(30000)
-
- for (const id of [ toRemove[0].id, toRemove[1].id ]) {
- await saveVideoInServers(servers, id)
-
- await servers[2].videos.remove({ id })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkVideoFilesWereRemoved({ server, video: server.store.videoDetails })
- }
- }
- })
-
- it('Should have videos 1 and 3 on each server', async function () {
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- expect(data).to.be.an('array')
- expect(data.length).to.equal(2)
- expect(data[0].name).not.to.equal(data[1].name)
- expect(data[0].name).not.to.equal(toRemove[0].name)
- expect(data[1].name).not.to.equal(toRemove[0].name)
- expect(data[0].name).not.to.equal(toRemove[1].name)
- expect(data[1].name).not.to.equal(toRemove[1].name)
-
- videoUUID = data.find(video => video.name === 'my super name for server 1').uuid
- }
- })
-
- it('Should get the same video by UUID on each server', async function () {
- let baseVideo = null
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- if (baseVideo === null) {
- baseVideo = video
- continue
- }
-
- expect(baseVideo.name).to.equal(video.name)
- expect(baseVideo.uuid).to.equal(video.uuid)
- expect(baseVideo.category.id).to.equal(video.category.id)
- expect(baseVideo.language.id).to.equal(video.language.id)
- expect(baseVideo.licence.id).to.equal(video.licence.id)
- expect(baseVideo.nsfw).to.equal(video.nsfw)
- expect(baseVideo.account.name).to.equal(video.account.name)
- expect(baseVideo.account.displayName).to.equal(video.account.displayName)
- expect(baseVideo.account.url).to.equal(video.account.url)
- expect(baseVideo.account.host).to.equal(video.account.host)
- expect(baseVideo.tags).to.deep.equal(video.tags)
- }
- })
-
- it('Should get the preview from each server', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- await testImageGeneratedByFFmpeg(server.url, 'video_short1-preview.webm', video.previewPath)
- }
- })
- })
-
- describe('Should comment these videos', function () {
- let childOfFirstChild: VideoCommentThreadTree
-
- it('Should add comment (threads and replies)', async function () {
- this.timeout(25000)
-
- {
- const text = 'my super first comment'
- await servers[0].comments.createThread({ videoId: videoUUID, text })
- }
-
- {
- const text = 'my super second comment'
- await servers[2].comments.createThread({ videoId: videoUUID, text })
- }
-
- await waitJobs(servers)
-
- {
- const threadId = await servers[1].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
-
- const text = 'my super answer to thread 1'
- await servers[1].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text })
- }
-
- await waitJobs(servers)
-
- {
- const threadId = await servers[2].comments.findCommentId({ videoId: videoUUID, text: 'my super first comment' })
-
- const body = await servers[2].comments.getThread({ videoId: videoUUID, threadId })
- const childCommentId = body.children[0].comment.id
-
- const text3 = 'my second answer to thread 1'
- await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: text3 })
-
- const text2 = 'my super answer to answer of thread 1'
- await servers[2].comments.addReply({ videoId: videoUUID, toCommentId: childCommentId, text: text2 })
- }
-
- await waitJobs(servers)
- })
-
- it('Should have these threads', async function () {
- for (const server of servers) {
- const body = await server.comments.listThreads({ videoId: videoUUID })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
-
- {
- const comment = body.data.find(c => c.text === 'my super first comment')
- expect(comment).to.not.be.undefined
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(servers[0].host)
- expect(comment.totalReplies).to.equal(3)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
- }
-
- {
- const comment = body.data.find(c => c.text === 'my super second comment')
- expect(comment).to.not.be.undefined
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(servers[2].host)
- expect(comment.totalReplies).to.equal(0)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
- }
- }
- })
-
- it('Should have these comments', async function () {
- for (const server of servers) {
- const body = await server.comments.listThreads({ videoId: videoUUID })
- const threadId = body.data.find(c => c.text === 'my super first comment').id
-
- const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
-
- expect(tree.comment.text).equal('my super first comment')
- expect(tree.comment.account.name).equal('root')
- expect(tree.comment.account.host).equal(servers[0].host)
- expect(tree.children).to.have.lengthOf(2)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('my super answer to thread 1')
- expect(firstChild.comment.account.name).equal('root')
- expect(firstChild.comment.account.host).equal(servers[1].host)
- expect(firstChild.children).to.have.lengthOf(1)
-
- childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
- expect(childOfFirstChild.comment.account.name).equal('root')
- expect(childOfFirstChild.comment.account.host).equal(servers[2].host)
- expect(childOfFirstChild.children).to.have.lengthOf(0)
-
- const secondChild = tree.children[1]
- expect(secondChild.comment.text).to.equal('my second answer to thread 1')
- expect(secondChild.comment.account.name).equal('root')
- expect(secondChild.comment.account.host).equal(servers[2].host)
- expect(secondChild.children).to.have.lengthOf(0)
- }
- })
-
- it('Should delete a reply', async function () {
- this.timeout(30000)
-
- await servers[2].comments.delete({ videoId: videoUUID, commentId: childOfFirstChild.comment.id })
-
- await waitJobs(servers)
- })
-
- it('Should have this comment marked as deleted', async function () {
- for (const server of servers) {
- const { data } = await server.comments.listThreads({ videoId: videoUUID })
- const threadId = data.find(c => c.text === 'my super first comment').id
-
- const tree = await server.comments.getThread({ videoId: videoUUID, threadId })
- expect(tree.comment.text).equal('my super first comment')
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('my super answer to thread 1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const deletedComment = firstChild.children[0].comment
- expect(deletedComment.isDeleted).to.be.true
- expect(deletedComment.deletedAt).to.not.be.null
- expect(deletedComment.account).to.be.null
- expect(deletedComment.text).to.equal('')
-
- const secondChild = tree.children[1]
- expect(secondChild.comment.text).to.equal('my second answer to thread 1')
- }
- })
-
- it('Should delete the thread comments', async function () {
- this.timeout(30000)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- const commentId = data.find(c => c.text === 'my super first comment').id
- await servers[0].comments.delete({ videoId: videoUUID, commentId })
-
- await waitJobs(servers)
- })
-
- it('Should have the threads marked as deleted on other servers too', async function () {
- for (const server of servers) {
- const body = await server.comments.listThreads({ videoId: videoUUID })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
-
- {
- const comment = body.data[0]
- expect(comment).to.not.be.undefined
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(servers[2].host)
- expect(comment.totalReplies).to.equal(0)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
- }
-
- {
- const deletedComment = body.data[1]
- expect(deletedComment).to.not.be.undefined
- expect(deletedComment.isDeleted).to.be.true
- expect(deletedComment.deletedAt).to.not.be.null
- expect(deletedComment.text).to.equal('')
- expect(deletedComment.inReplyToCommentId).to.be.null
- expect(deletedComment.account).to.be.null
- expect(deletedComment.totalReplies).to.equal(2)
- expect(dateIsValid(deletedComment.createdAt as string)).to.be.true
- expect(dateIsValid(deletedComment.updatedAt as string)).to.be.true
- expect(dateIsValid(deletedComment.deletedAt as string)).to.be.true
- }
- }
- })
-
- it('Should delete a remote thread by the origin server', async function () {
- this.timeout(5000)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- const commentId = data.find(c => c.text === 'my super second comment').id
- await servers[0].comments.delete({ videoId: videoUUID, commentId })
-
- await waitJobs(servers)
- })
-
- it('Should have the threads marked as deleted on other servers too', async function () {
- for (const server of servers) {
- const body = await server.comments.listThreads({ videoId: videoUUID })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- {
- const comment = body.data[0]
- expect(comment.text).to.equal('')
- expect(comment.isDeleted).to.be.true
- expect(comment.createdAt).to.not.be.null
- expect(comment.deletedAt).to.not.be.null
- expect(comment.account).to.be.null
- expect(comment.totalReplies).to.equal(0)
- }
-
- {
- const comment = body.data[1]
- expect(comment.text).to.equal('')
- expect(comment.isDeleted).to.be.true
- expect(comment.createdAt).to.not.be.null
- expect(comment.deletedAt).to.not.be.null
- expect(comment.account).to.be.null
- expect(comment.totalReplies).to.equal(2)
- }
- }
- })
-
- it('Should disable comments and download', async function () {
- this.timeout(20000)
-
- const attributes = {
- commentsEnabled: false,
- downloadEnabled: false
- }
-
- await servers[0].videos.update({ id: videoUUID, attributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.commentsEnabled).to.be.false
- expect(video.downloadEnabled).to.be.false
-
- const text = 'my super forbidden comment'
- await server.comments.createThread({ videoId: videoUUID, text, expectedStatus: HttpStatusCode.CONFLICT_409 })
- }
- })
- })
-
- describe('With minimum parameters', function () {
- it('Should upload and propagate the video', async function () {
- this.timeout(120000)
-
- const path = '/api/v1/videos/upload'
-
- const req = request(servers[1].url)
- .post(path)
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + servers[1].accessToken)
- .field('name', 'minimum parameters')
- .field('privacy', '1')
- .field('channelId', '1')
-
- await req.attach('videofile', buildAbsoluteFixturePath('video_short.webm'))
- .expect(HttpStatusCode.OK_200)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- const video = data.find(v => v.name === 'minimum parameters')
-
- const isLocal = server.url === servers[1].url
- const checkAttributes = {
- name: 'minimum parameters',
- category: null,
- licence: null,
- language: null,
- nsfw: false,
- description: null,
- support: null,
- account: {
- name: 'root',
- host: servers[1].host
- },
- isLocal,
- duration: 5,
- commentsEnabled: true,
- downloadEnabled: true,
- tags: [],
- privacy: VideoPrivacy.PUBLIC,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal
- },
- fixture: 'video_short.webm',
- files: [
- {
- resolution: 720,
- size: 61000
- },
- {
- resolution: 480,
- size: 40000
- },
- {
- resolution: 360,
- size: 32000
- },
- {
- resolution: 240,
- size: 23000
- }
- ]
- }
- await completeVideoCheck({ server, originServer: servers[1], videoUUID: video.uuid, attributes: checkAttributes })
- }
- })
- })
-
- describe('TMP directory', function () {
- it('Should have an empty tmp directory', async function () {
- for (const server of servers) {
- await checkTmpIsEmpty(server)
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/resumable-upload.ts b/server/tests/api/videos/resumable-upload.ts
deleted file mode 100644
index cac1201e9..000000000
--- a/server/tests/api/videos/resumable-upload.ts
+++ /dev/null
@@ -1,310 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir, stat } from 'fs-extra'
-import { join } from 'path'
-import { buildAbsoluteFixturePath } from '@shared/core-utils'
-import { sha1 } from '@shared/extra-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/server-commands'
-
-// Most classic resumable upload tests are done in other test suites
-
-describe('Test resumable upload', function () {
- const path = '/api/v1/videos/upload-resumable'
- const defaultFixture = 'video_short.mp4'
- let server: PeerTubeServer
- let rootId: number
- let userAccessToken: string
- let userChannelId: number
-
- async function buildSize (fixture: string, size?: number) {
- if (size !== undefined) return size
-
- const baseFixture = buildAbsoluteFixturePath(fixture)
- return (await stat(baseFixture)).size
- }
-
- async function prepareUpload (options: {
- channelId?: number
- token?: string
- size?: number
- originalName?: string
- lastModified?: number
- } = {}) {
- const { token, originalName, lastModified } = options
-
- const size = await buildSize(defaultFixture, options.size)
-
- const attributes = {
- name: 'video',
- channelId: options.channelId ?? server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- fixture: defaultFixture
- }
-
- const mimetype = 'video/mp4'
-
- const res = await server.videos.prepareResumableUpload({ path, token, attributes, size, mimetype, originalName, lastModified })
-
- return res.header['location'].split('?')[1]
- }
-
- async function sendChunks (options: {
- token?: string
- pathUploadId: string
- size?: number
- expectedStatus?: HttpStatusCode
- contentLength?: number
- contentRange?: string
- contentRangeBuilder?: (start: number, chunk: any) => string
- digestBuilder?: (chunk: any) => string
- }) {
- const { token, pathUploadId, expectedStatus, contentLength, contentRangeBuilder, digestBuilder } = options
-
- const size = await buildSize(defaultFixture, options.size)
- const absoluteFilePath = buildAbsoluteFixturePath(defaultFixture)
-
- return server.videos.sendResumableChunks({
- token,
- path,
- pathUploadId,
- videoFilePath: absoluteFilePath,
- size,
- contentLength,
- contentRangeBuilder,
- digestBuilder,
- expectedStatus
- })
- }
-
- async function checkFileSize (uploadIdArg: string, expectedSize: number | null) {
- const uploadId = uploadIdArg.replace(/^upload_id=/, '')
-
- const subPath = join('tmp', 'resumable-uploads', `${rootId}-${uploadId}.mp4`)
- const filePath = server.servers.buildDirectory(subPath)
- const exists = await pathExists(filePath)
-
- if (expectedSize === null) {
- expect(exists).to.be.false
- return
- }
-
- expect(exists).to.be.true
-
- expect((await stat(filePath)).size).to.equal(expectedSize)
- }
-
- async function countResumableUploads (wait?: number) {
- const subPath = join('tmp', 'resumable-uploads')
- const filePath = server.servers.buildDirectory(subPath)
- await new Promise(resolve => setTimeout(resolve, wait))
- const files = await readdir(filePath)
- return files.length
- }
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- const body = await server.users.getMyInfo()
- rootId = body.id
-
- {
- userAccessToken = await server.users.generateUserAndToken('user1')
- const { videoChannels } = await server.users.getMyInfo({ token: userAccessToken })
- userChannelId = videoChannels[0].id
- }
-
- await server.users.update({ userId: rootId, videoQuota: 10_000_000 })
- })
-
- describe('Directory cleaning', function () {
-
- it('Should correctly delete files after an upload', async function () {
- const uploadId = await prepareUpload()
- await sendChunks({ pathUploadId: uploadId })
- await server.videos.endResumableUpload({ path, pathUploadId: uploadId })
-
- expect(await countResumableUploads()).to.equal(0)
- })
-
- it('Should correctly delete corrupt files', async function () {
- const uploadId = await prepareUpload({ size: 8 * 1024 })
- await sendChunks({ pathUploadId: uploadId, size: 8 * 1024, expectedStatus: HttpStatusCode.UNPROCESSABLE_ENTITY_422 })
-
- expect(await countResumableUploads(2000)).to.equal(0)
- })
-
- it('Should not delete files after an unfinished upload', async function () {
- await prepareUpload()
-
- expect(await countResumableUploads()).to.equal(2)
- })
-
- it('Should not delete recent uploads', async function () {
- await server.debug.sendCommand({ body: { command: 'remove-dandling-resumable-uploads' } })
-
- expect(await countResumableUploads()).to.equal(2)
- })
-
- it('Should delete old uploads', async function () {
- await server.debug.sendCommand({ body: { command: 'remove-dandling-resumable-uploads' } })
-
- expect(await countResumableUploads()).to.equal(0)
- })
- })
-
- describe('Resumable upload and chunks', function () {
-
- it('Should accept the same amount of chunks', async function () {
- const uploadId = await prepareUpload()
- await sendChunks({ pathUploadId: uploadId })
-
- await checkFileSize(uploadId, null)
- })
-
- it('Should not accept more chunks than expected', async function () {
- const uploadId = await prepareUpload({ size: 100 })
-
- await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409 })
- await checkFileSize(uploadId, 0)
- })
-
- it('Should not accept more chunks than expected with an invalid content length/content range', async function () {
- const uploadId = await prepareUpload({ size: 1500 })
-
- // Content length check can be different depending on the node version
- try {
- await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.CONFLICT_409, contentLength: 1000 })
- await checkFileSize(uploadId, 0)
- } catch {
- await sendChunks({ pathUploadId: uploadId, expectedStatus: HttpStatusCode.BAD_REQUEST_400, contentLength: 1000 })
- await checkFileSize(uploadId, 0)
- }
- })
-
- it('Should not accept more chunks than expected with an invalid content length', async function () {
- const uploadId = await prepareUpload({ size: 500 })
-
- const size = 1000
-
- // Content length check seems to have changed in v16
- const expectedStatus = process.version.startsWith('v16')
- ? HttpStatusCode.CONFLICT_409
- : HttpStatusCode.BAD_REQUEST_400
-
- const contentRangeBuilder = (start: number) => `bytes ${start}-${start + size - 1}/${size}`
- await sendChunks({ pathUploadId: uploadId, expectedStatus, contentRangeBuilder, contentLength: size })
- await checkFileSize(uploadId, 0)
- })
-
- it('Should be able to accept 2 PUT requests', async function () {
- const uploadId = await prepareUpload()
-
- const result1 = await sendChunks({ pathUploadId: uploadId })
- const result2 = await sendChunks({ pathUploadId: uploadId })
-
- expect(result1.body.video.uuid).to.exist
- expect(result1.body.video.uuid).to.equal(result2.body.video.uuid)
-
- expect(result1.headers['x-resumable-upload-cached']).to.not.exist
- expect(result2.headers['x-resumable-upload-cached']).to.equal('true')
-
- await checkFileSize(uploadId, null)
- })
-
- it('Should not have the same upload id with 2 different users', async function () {
- const originalName = 'toto.mp4'
- const lastModified = new Date().getTime()
-
- const uploadId1 = await prepareUpload({ originalName, lastModified, token: server.accessToken })
- const uploadId2 = await prepareUpload({ originalName, lastModified, channelId: userChannelId, token: userAccessToken })
-
- expect(uploadId1).to.not.equal(uploadId2)
- })
-
- it('Should have the same upload id with the same user', async function () {
- const originalName = 'toto.mp4'
- const lastModified = new Date().getTime()
-
- const uploadId1 = await prepareUpload({ originalName, lastModified })
- const uploadId2 = await prepareUpload({ originalName, lastModified })
-
- expect(uploadId1).to.equal(uploadId2)
- })
-
- it('Should not cache a request with 2 different users', async function () {
- const originalName = 'toto.mp4'
- const lastModified = new Date().getTime()
-
- const uploadId = await prepareUpload({ originalName, lastModified, token: server.accessToken })
-
- await sendChunks({ pathUploadId: uploadId, token: server.accessToken })
- await sendChunks({ pathUploadId: uploadId, token: userAccessToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should not cache a request after a delete', async function () {
- const originalName = 'toto.mp4'
- const lastModified = new Date().getTime()
- const uploadId1 = await prepareUpload({ originalName, lastModified, token: server.accessToken })
-
- await sendChunks({ pathUploadId: uploadId1 })
- await server.videos.endResumableUpload({ path, pathUploadId: uploadId1 })
-
- const uploadId2 = await prepareUpload({ originalName, lastModified, token: server.accessToken })
- expect(uploadId1).to.equal(uploadId2)
-
- const result2 = await sendChunks({ pathUploadId: uploadId1 })
- expect(result2.headers['x-resumable-upload-cached']).to.not.exist
- })
-
- it('Should not cache after video deletion', async function () {
- const originalName = 'toto.mp4'
- const lastModified = new Date().getTime()
-
- const uploadId1 = await prepareUpload({ originalName, lastModified })
- const result1 = await sendChunks({ pathUploadId: uploadId1 })
- await server.videos.remove({ id: result1.body.video.uuid })
-
- const uploadId2 = await prepareUpload({ originalName, lastModified })
- const result2 = await sendChunks({ pathUploadId: uploadId2 })
- expect(result1.body.video.uuid).to.not.equal(result2.body.video.uuid)
-
- expect(result2.headers['x-resumable-upload-cached']).to.not.exist
-
- await checkFileSize(uploadId1, null)
- await checkFileSize(uploadId2, null)
- })
-
- it('Should refuse an invalid digest', async function () {
- const uploadId = await prepareUpload({ token: server.accessToken })
-
- await sendChunks({
- pathUploadId: uploadId,
- token: server.accessToken,
- digestBuilder: () => 'sha=' + 'a'.repeat(40),
- expectedStatus: 460 as any
- })
- })
-
- it('Should accept an appropriate digest', async function () {
- const uploadId = await prepareUpload({ token: server.accessToken })
-
- await sendChunks({
- pathUploadId: uploadId,
- token: server.accessToken,
- digestBuilder: (chunk: Buffer) => {
- return 'sha1=' + sha1(chunk, 'base64')
- }
- })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts
deleted file mode 100644
index 66414aa5b..000000000
--- a/server/tests/api/videos/single-server.ts
+++ /dev/null
@@ -1,460 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkVideoFilesWereRemoved, completeVideoCheck, testImageGeneratedByFFmpeg } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { Video, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test a single server', function () {
-
- function runSuite (mode: 'legacy' | 'resumable') {
- let server: PeerTubeServer = null
- let videoId: number | string
- let videoId2: string
- let videoUUID = ''
- let videosListBase: any[] = null
-
- const getCheckAttributes = () => ({
- name: 'my super name',
- category: 2,
- licence: 6,
- language: 'zh',
- nsfw: true,
- description: 'my super description',
- support: 'my super support text',
- account: {
- name: 'root',
- host: server.host
- },
- isLocal: true,
- duration: 5,
- tags: [ 'tag1', 'tag2', 'tag3' ],
- privacy: VideoPrivacy.PUBLIC,
- commentsEnabled: true,
- downloadEnabled: true,
- channel: {
- displayName: 'Main root channel',
- name: 'root_channel',
- description: '',
- isLocal: true
- },
- fixture: 'video_short.webm',
- files: [
- {
- resolution: 720,
- size: 218910
- }
- ]
- })
-
- const updateCheckAttributes = () => ({
- name: 'my super video updated',
- category: 4,
- licence: 2,
- language: 'ar',
- nsfw: false,
- description: 'my super description updated',
- support: 'my super support text updated',
- account: {
- name: 'root',
- host: server.host
- },
- isLocal: true,
- tags: [ 'tagup1', 'tagup2' ],
- privacy: VideoPrivacy.PUBLIC,
- duration: 5,
- commentsEnabled: false,
- downloadEnabled: false,
- channel: {
- name: 'root_channel',
- displayName: 'Main root channel',
- description: '',
- isLocal: true
- },
- fixture: 'video_short3.webm',
- files: [
- {
- resolution: 720,
- size: 292677
- }
- ]
- })
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(server)
- })
-
- it('Should list video categories', async function () {
- const categories = await server.videos.getCategories()
- expect(Object.keys(categories)).to.have.length.above(10)
-
- expect(categories[11]).to.equal('News & Politics')
- })
-
- it('Should list video licences', async function () {
- const licences = await server.videos.getLicences()
- expect(Object.keys(licences)).to.have.length.above(5)
-
- expect(licences[3]).to.equal('Attribution - No Derivatives')
- })
-
- it('Should list video languages', async function () {
- const languages = await server.videos.getLanguages()
- expect(Object.keys(languages)).to.have.length.above(5)
-
- expect(languages['ru']).to.equal('Russian')
- })
-
- it('Should list video privacies', async function () {
- const privacies = await server.videos.getPrivacies()
- expect(Object.keys(privacies)).to.have.length.at.least(3)
-
- expect(privacies[3]).to.equal('Private')
- })
-
- it('Should not have videos', async function () {
- const { data, total } = await server.videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(0)
- })
-
- it('Should upload the video', async function () {
- const attributes = {
- name: 'my super name',
- category: 2,
- nsfw: true,
- licence: 6,
- tags: [ 'tag1', 'tag2', 'tag3' ]
- }
- const video = await server.videos.upload({ attributes, mode })
- expect(video).to.not.be.undefined
- expect(video.id).to.equal(1)
- expect(video.uuid).to.have.length.above(5)
-
- videoId = video.id
- videoUUID = video.uuid
- })
-
- it('Should get and seed the uploaded video', async function () {
- this.timeout(5000)
-
- const { data, total } = await server.videos.list()
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data.length).to.equal(1)
-
- const video = data[0]
- await completeVideoCheck({ server, originServer: server, videoUUID: video.uuid, attributes: getCheckAttributes() })
- })
-
- it('Should get the video by UUID', async function () {
- this.timeout(5000)
-
- const video = await server.videos.get({ id: videoUUID })
- await completeVideoCheck({ server, originServer: server, videoUUID: video.uuid, attributes: getCheckAttributes() })
- })
-
- it('Should have the views updated', async function () {
- this.timeout(20000)
-
- await server.views.simulateView({ id: videoId })
- await server.views.simulateView({ id: videoId })
- await server.views.simulateView({ id: videoId })
-
- await wait(1500)
-
- await server.views.simulateView({ id: videoId })
- await server.views.simulateView({ id: videoId })
-
- await wait(1500)
-
- await server.views.simulateView({ id: videoId })
- await server.views.simulateView({ id: videoId })
-
- await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } })
-
- const video = await server.videos.get({ id: videoId })
- expect(video.views).to.equal(3)
- })
-
- it('Should remove the video', async function () {
- const video = await server.videos.get({ id: videoId })
- await server.videos.remove({ id: videoId })
-
- await checkVideoFilesWereRemoved({ video, server })
- })
-
- it('Should not have videos', async function () {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(0)
- })
-
- it('Should upload 6 videos', async function () {
- this.timeout(120000)
-
- const videos = new Set([
- 'video_short.mp4', 'video_short.ogv', 'video_short.webm',
- 'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
- ])
-
- for (const video of videos) {
- const attributes = {
- name: video + ' name',
- description: video + ' description',
- category: 2,
- licence: 1,
- language: 'en',
- nsfw: true,
- tags: [ 'tag1', 'tag2', 'tag3' ],
- fixture: video
- }
-
- await server.videos.upload({ attributes, mode })
- }
- })
-
- it('Should have the correct durations', async function () {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(6)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(6)
-
- const videosByName: { [ name: string ]: Video } = {}
- data.forEach(v => { videosByName[v.name] = v })
-
- expect(videosByName['video_short.mp4 name'].duration).to.equal(5)
- expect(videosByName['video_short.ogv name'].duration).to.equal(5)
- expect(videosByName['video_short.webm name'].duration).to.equal(5)
- expect(videosByName['video_short1.webm name'].duration).to.equal(10)
- expect(videosByName['video_short2.webm name'].duration).to.equal(5)
- expect(videosByName['video_short3.webm name'].duration).to.equal(5)
- })
-
- it('Should have the correct thumbnails', async function () {
- const { data } = await server.videos.list()
-
- // For the next test
- videosListBase = data
-
- for (const video of data) {
- const videoName = video.name.replace(' name', '')
- await testImageGeneratedByFFmpeg(server.url, videoName, video.thumbnailPath)
- }
- })
-
- it('Should list only the two first videos', async function () {
- const { total, data } = await server.videos.list({ start: 0, count: 2, sort: 'name' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(2)
- expect(data[0].name).to.equal(videosListBase[0].name)
- expect(data[1].name).to.equal(videosListBase[1].name)
- })
-
- it('Should list only the next three videos', async function () {
- const { total, data } = await server.videos.list({ start: 2, count: 3, sort: 'name' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(3)
- expect(data[0].name).to.equal(videosListBase[2].name)
- expect(data[1].name).to.equal(videosListBase[3].name)
- expect(data[2].name).to.equal(videosListBase[4].name)
- })
-
- it('Should list the last video', async function () {
- const { total, data } = await server.videos.list({ start: 5, count: 6, sort: 'name' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(1)
- expect(data[0].name).to.equal(videosListBase[5].name)
- })
-
- it('Should not have the total field', async function () {
- const { total, data } = await server.videos.list({ start: 5, count: 6, sort: 'name', skipCount: true })
-
- expect(total).to.not.exist
- expect(data.length).to.equal(1)
- expect(data[0].name).to.equal(videosListBase[5].name)
- })
-
- it('Should list and sort by name in descending order', async function () {
- const { total, data } = await server.videos.list({ sort: '-name' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(6)
- expect(data[0].name).to.equal('video_short.webm name')
- expect(data[1].name).to.equal('video_short.ogv name')
- expect(data[2].name).to.equal('video_short.mp4 name')
- expect(data[3].name).to.equal('video_short3.webm name')
- expect(data[4].name).to.equal('video_short2.webm name')
- expect(data[5].name).to.equal('video_short1.webm name')
-
- videoId = data[3].uuid
- videoId2 = data[5].uuid
- })
-
- it('Should list and sort by trending in descending order', async function () {
- const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-trending' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(2)
- })
-
- it('Should list and sort by hotness in descending order', async function () {
- const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-hot' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(2)
- })
-
- it('Should list and sort by best in descending order', async function () {
- const { total, data } = await server.videos.list({ start: 0, count: 2, sort: '-best' })
-
- expect(total).to.equal(6)
- expect(data.length).to.equal(2)
- })
-
- it('Should update a video', async function () {
- const attributes = {
- name: 'my super video updated',
- category: 4,
- licence: 2,
- language: 'ar',
- nsfw: false,
- description: 'my super description updated',
- commentsEnabled: false,
- downloadEnabled: false,
- tags: [ 'tagup1', 'tagup2' ]
- }
- await server.videos.update({ id: videoId, attributes })
- })
-
- it('Should have the video updated', async function () {
- this.timeout(60000)
-
- await waitJobs([ server ])
-
- const video = await server.videos.get({ id: videoId })
-
- await completeVideoCheck({ server, originServer: server, videoUUID: video.uuid, attributes: updateCheckAttributes() })
- })
-
- it('Should update only the tags of a video', async function () {
- const attributes = {
- tags: [ 'supertag', 'tag1', 'tag2' ]
- }
- await server.videos.update({ id: videoId, attributes })
-
- const video = await server.videos.get({ id: videoId })
-
- await completeVideoCheck({
- server,
- originServer: server,
- videoUUID: video.uuid,
- attributes: Object.assign(updateCheckAttributes(), attributes)
- })
- })
-
- it('Should update only the description of a video', async function () {
- const attributes = {
- description: 'hello everybody'
- }
- await server.videos.update({ id: videoId, attributes })
-
- const video = await server.videos.get({ id: videoId })
-
- await completeVideoCheck({
- server,
- originServer: server,
- videoUUID: video.uuid,
- attributes: Object.assign(updateCheckAttributes(), { tags: [ 'supertag', 'tag1', 'tag2' ] }, attributes)
- })
- })
-
- it('Should like a video', async function () {
- await server.videos.rate({ id: videoId, rating: 'like' })
-
- const video = await server.videos.get({ id: videoId })
-
- expect(video.likes).to.equal(1)
- expect(video.dislikes).to.equal(0)
- })
-
- it('Should dislike the same video', async function () {
- await server.videos.rate({ id: videoId, rating: 'dislike' })
-
- const video = await server.videos.get({ id: videoId })
-
- expect(video.likes).to.equal(0)
- expect(video.dislikes).to.equal(1)
- })
-
- it('Should sort by originallyPublishedAt', async function () {
- {
- const now = new Date()
- const attributes = { originallyPublishedAt: now.toISOString() }
- await server.videos.update({ id: videoId, attributes })
-
- const { data } = await server.videos.list({ sort: '-originallyPublishedAt' })
- const names = data.map(v => v.name)
-
- expect(names[0]).to.equal('my super video updated')
- expect(names[1]).to.equal('video_short2.webm name')
- expect(names[2]).to.equal('video_short1.webm name')
- expect(names[3]).to.equal('video_short.webm name')
- expect(names[4]).to.equal('video_short.ogv name')
- expect(names[5]).to.equal('video_short.mp4 name')
- }
-
- {
- const now = new Date()
- const attributes = { originallyPublishedAt: now.toISOString() }
- await server.videos.update({ id: videoId2, attributes })
-
- const { data } = await server.videos.list({ sort: '-originallyPublishedAt' })
- const names = data.map(v => v.name)
-
- expect(names[0]).to.equal('video_short1.webm name')
- expect(names[1]).to.equal('my super video updated')
- expect(names[2]).to.equal('video_short2.webm name')
- expect(names[3]).to.equal('video_short.webm name')
- expect(names[4]).to.equal('video_short.ogv name')
- expect(names[5]).to.equal('video_short.mp4 name')
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
- }
-
- describe('Legacy upload', function () {
- runSuite('legacy')
- })
-
- describe('Resumable upload', function () {
- runSuite('resumable')
- })
-})
diff --git a/server/tests/api/videos/video-captions.ts b/server/tests/api/videos/video-captions.ts
deleted file mode 100644
index 0630c9d3a..000000000
--- a/server/tests/api/videos/video-captions.ts
+++ /dev/null
@@ -1,188 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkVideoFilesWereRemoved, testCaptionFile } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video captions', function () {
- const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
-
- let servers: PeerTubeServer[]
- let videoUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await doubleFollow(servers[0], servers[1])
-
- await waitJobs(servers)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video name' } })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should list the captions and return an empty list', async function () {
- for (const server of servers) {
- const body = await server.captions.list({ videoId: videoUUID })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should create two new captions', async function () {
- this.timeout(30000)
-
- await servers[0].captions.add({
- language: 'ar',
- videoId: videoUUID,
- fixture: 'subtitle-good1.vtt'
- })
-
- await servers[0].captions.add({
- language: 'zh',
- videoId: videoUUID,
- fixture: 'subtitle-good2.vtt',
- mimeType: 'application/octet-stream'
- })
-
- await waitJobs(servers)
- })
-
- it('Should list these uploaded captions', async function () {
- for (const server of servers) {
- const body = await server.captions.list({ videoId: videoUUID })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- const caption1 = body.data[0]
- expect(caption1.language.id).to.equal('ar')
- expect(caption1.language.label).to.equal('Arabic')
- expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
- await testCaptionFile(server.url, caption1.captionPath, 'Subtitle good 1.')
-
- const caption2 = body.data[1]
- expect(caption2.language.id).to.equal('zh')
- expect(caption2.language.label).to.equal('Chinese')
- expect(caption2.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-zh.vtt$'))
- await testCaptionFile(server.url, caption2.captionPath, 'Subtitle good 2.')
- }
- })
-
- it('Should replace an existing caption', async function () {
- this.timeout(30000)
-
- await servers[0].captions.add({
- language: 'ar',
- videoId: videoUUID,
- fixture: 'subtitle-good2.vtt'
- })
-
- await waitJobs(servers)
- })
-
- it('Should have this caption updated', async function () {
- for (const server of servers) {
- const body = await server.captions.list({ videoId: videoUUID })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- const caption1 = body.data[0]
- expect(caption1.language.id).to.equal('ar')
- expect(caption1.language.label).to.equal('Arabic')
- expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
- await testCaptionFile(server.url, caption1.captionPath, 'Subtitle good 2.')
- }
- })
-
- it('Should replace an existing caption with a srt file and convert it', async function () {
- this.timeout(30000)
-
- await servers[0].captions.add({
- language: 'ar',
- videoId: videoUUID,
- fixture: 'subtitle-good.srt'
- })
-
- await waitJobs(servers)
-
- // Cache invalidation
- await wait(3000)
- })
-
- it('Should have this caption updated and converted', async function () {
- for (const server of servers) {
- const body = await server.captions.list({ videoId: videoUUID })
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(2)
-
- const caption1 = body.data[0]
- expect(caption1.language.id).to.equal('ar')
- expect(caption1.language.label).to.equal('Arabic')
- expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-ar.vtt$'))
-
- const expected = 'WEBVTT FILE\r\n' +
- '\r\n' +
- '1\r\n' +
- '00:00:01.600 --> 00:00:04.200\r\n' +
- 'English (US)\r\n' +
- '\r\n' +
- '2\r\n' +
- '00:00:05.900 --> 00:00:07.999\r\n' +
- 'This is a subtitle in American English\r\n' +
- '\r\n' +
- '3\r\n' +
- '00:00:10.000 --> 00:00:14.000\r\n' +
- 'Adding subtitles is very easy to do\r\n'
- await testCaptionFile(server.url, caption1.captionPath, expected)
- }
- })
-
- it('Should remove one caption', async function () {
- this.timeout(30000)
-
- await servers[0].captions.delete({ videoId: videoUUID, language: 'ar' })
-
- await waitJobs(servers)
- })
-
- it('Should only list the caption that was not deleted', async function () {
- for (const server of servers) {
- const body = await server.captions.list({ videoId: videoUUID })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const caption = body.data[0]
-
- expect(caption.language.id).to.equal('zh')
- expect(caption.language.label).to.equal('Chinese')
- expect(caption.captionPath).to.match(new RegExp('^/lazy-static/video-captions/' + uuidRegex + '-zh.vtt$'))
- await testCaptionFile(server.url, caption.captionPath, 'Subtitle good 2.')
- }
- })
-
- it('Should remove the video, and thus all video captions', async function () {
- const video = await servers[0].videos.get({ id: videoUUID })
- const { data: captions } = await servers[0].captions.list({ videoId: videoUUID })
-
- await servers[0].videos.remove({ id: videoUUID })
-
- await checkVideoFilesWereRemoved({ server: servers[0], video, captions })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-change-ownership.ts b/server/tests/api/videos/video-change-ownership.ts
deleted file mode 100644
index 99d774c2b..000000000
--- a/server/tests/api/videos/video-change-ownership.ts
+++ /dev/null
@@ -1,314 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- ChangeOwnershipCommand,
- cleanupTests,
- createMultipleServers,
- createSingleServer,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-
-describe('Test video change ownership - nominal', function () {
- let servers: PeerTubeServer[] = []
-
- const firstUser = 'first'
- const secondUser = 'second'
-
- let firstUserToken = ''
- let firstUserChannelId: number
-
- let secondUserToken = ''
- let secondUserChannelId: number
-
- let lastRequestId: number
-
- let liveId: number
-
- let command: ChangeOwnershipCommand
-
- before(async function () {
- this.timeout(50000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: false
- },
- live: {
- enabled: true
- }
- }
- })
-
- firstUserToken = await servers[0].users.generateUserAndToken(firstUser)
- secondUserToken = await servers[0].users.generateUserAndToken(secondUser)
-
- {
- const { videoChannels } = await servers[0].users.getMyInfo({ token: firstUserToken })
- firstUserChannelId = videoChannels[0].id
- }
-
- {
- const { videoChannels } = await servers[0].users.getMyInfo({ token: secondUserToken })
- secondUserChannelId = videoChannels[0].id
- }
-
- {
- const attributes = {
- name: 'my super name',
- description: 'my super description'
- }
- const { id } = await servers[0].videos.upload({ token: firstUserToken, attributes })
-
- servers[0].store.videoCreated = await servers[0].videos.get({ id })
- }
-
- {
- const attributes = { name: 'live', channelId: firstUserChannelId, privacy: VideoPrivacy.PUBLIC }
- const video = await servers[0].live.create({ token: firstUserToken, fields: attributes })
-
- liveId = video.id
- }
-
- command = servers[0].changeOwnership
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should not have video change ownership', async function () {
- {
- const body = await command.list({ token: firstUserToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await command.list({ token: secondUserToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
- })
-
- it('Should send a request to change ownership of a video', async function () {
- this.timeout(15000)
-
- await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
- })
-
- it('Should only return a request to change ownership for the second user', async function () {
- {
- const body = await command.list({ token: firstUserToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await command.list({ token: secondUserToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
-
- lastRequestId = body.data[0].id
- }
- })
-
- it('Should accept the same change ownership request without crashing', async function () {
- await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
- })
-
- it('Should not create multiple change ownership requests while one is waiting', async function () {
- const body = await command.list({ token: secondUserToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
- })
-
- it('Should not be possible to refuse the change of ownership from first user', async function () {
- await command.refuse({ token: firstUserToken, ownershipId: lastRequestId, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should be possible to refuse the change of ownership from second user', async function () {
- await command.refuse({ token: secondUserToken, ownershipId: lastRequestId })
- })
-
- it('Should send a new request to change ownership of a video', async function () {
- this.timeout(15000)
-
- await command.create({ token: firstUserToken, videoId: servers[0].store.videoCreated.id, username: secondUser })
- })
-
- it('Should return two requests to change ownership for the second user', async function () {
- {
- const body = await command.list({ token: firstUserToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await command.list({ token: secondUserToken })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(2)
-
- lastRequestId = body.data[0].id
- }
- })
-
- it('Should not be possible to accept the change of ownership from first user', async function () {
- await command.accept({
- token: firstUserToken,
- ownershipId: lastRequestId,
- channelId: secondUserChannelId,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should be possible to accept the change of ownership from second user', async function () {
- await command.accept({ token: secondUserToken, ownershipId: lastRequestId, channelId: secondUserChannelId })
-
- await waitJobs(servers)
- })
-
- it('Should have the channel of the video updated', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
-
- expect(video.name).to.equal('my super name')
- expect(video.channel.displayName).to.equal('Main second channel')
- expect(video.channel.name).to.equal('second_channel')
- }
- })
-
- it('Should send a request to change ownership of a live', async function () {
- this.timeout(15000)
-
- await command.create({ token: firstUserToken, videoId: liveId, username: secondUser })
-
- const body = await command.list({ token: secondUserToken })
-
- expect(body.total).to.equal(3)
- expect(body.data.length).to.equal(3)
-
- lastRequestId = body.data[0].id
- })
-
- it('Should accept a live ownership change', async function () {
- this.timeout(20000)
-
- await command.accept({ token: secondUserToken, ownershipId: lastRequestId, channelId: secondUserChannelId })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: servers[0].store.videoCreated.uuid })
-
- expect(video.name).to.equal('my super name')
- expect(video.channel.displayName).to.equal('Main second channel')
- expect(video.channel.name).to.equal('second_channel')
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
-
-describe('Test video change ownership - quota too small', function () {
- let server: PeerTubeServer
- const firstUser = 'first'
- const secondUser = 'second'
-
- let firstUserToken = ''
- let secondUserToken = ''
- let lastRequestId: number
-
- before(async function () {
- this.timeout(50000)
-
- // Run one server
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.users.create({ username: secondUser, videoQuota: 10 })
-
- firstUserToken = await server.users.generateUserAndToken(firstUser)
- secondUserToken = await server.login.getAccessToken(secondUser)
-
- // Upload some videos on the server
- const attributes = {
- name: 'my super name',
- description: 'my super description'
- }
- await server.videos.upload({ token: firstUserToken, attributes })
-
- await waitJobs(server)
-
- const { data } = await server.videos.list()
- expect(data.length).to.equal(1)
-
- server.store.videoCreated = data.find(video => video.name === 'my super name')
- })
-
- it('Should send a request to change ownership of a video', async function () {
- this.timeout(15000)
-
- await server.changeOwnership.create({ token: firstUserToken, videoId: server.store.videoCreated.id, username: secondUser })
- })
-
- it('Should only return a request to change ownership for the second user', async function () {
- {
- const body = await server.changeOwnership.list({ token: firstUserToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(0)
- }
-
- {
- const body = await server.changeOwnership.list({ token: secondUserToken })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data.length).to.equal(1)
-
- lastRequestId = body.data[0].id
- }
- })
-
- it('Should not be possible to accept the change of ownership from second user because of exceeded quota', async function () {
- const { videoChannels } = await server.users.getMyInfo({ token: secondUserToken })
- const channelId = videoChannels[0].id
-
- await server.changeOwnership.accept({
- token: secondUserToken,
- ownershipId: lastRequestId,
- channelId,
- expectedStatus: HttpStatusCode.PAYLOAD_TOO_LARGE_413
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/video-channel-syncs.ts b/server/tests/api/videos/video-channel-syncs.ts
deleted file mode 100644
index 7f688c7d6..000000000
--- a/server/tests/api/videos/video-channel-syncs.ts
+++ /dev/null
@@ -1,320 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FIXTURE_URLS, SQLCommand } from '@server/tests/shared'
-import { areHttpImportTestsDisabled } from '@shared/core-utils'
-import { VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- getServerImportConfig,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test channel synchronizations', function () {
- if (areHttpImportTestsDisabled()) return
-
- function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
-
- describe('Sync using ' + mode, function () {
- let servers: PeerTubeServer[]
- let sqlCommands: SQLCommand[] = []
-
- let startTestDate: Date
-
- let rootChannelSyncId: number
- const userInfo = {
- accessToken: '',
- username: 'user1',
- channelName: 'user1_channel',
- channelId: -1,
- syncId: -1
- }
-
- async function changeDateForSync (channelSyncId: number, newDate: string) {
- await sqlCommands[0].updateQuery(
- `UPDATE "videoChannelSync" ` +
- `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
- `WHERE id=${channelSyncId}`
- )
- }
-
- async function listAllVideosOfChannel (channelName: string) {
- return servers[0].videos.listByChannel({
- handle: channelName,
- include: VideoInclude.NOT_PUBLISHED_STATE
- })
- }
-
- async function forceSyncAll (videoChannelSyncId: number, fromDate = '1970-01-01') {
- await changeDateForSync(videoChannelSyncId, fromDate)
-
- await servers[0].debug.sendCommand({
- body: {
- command: 'process-video-channel-sync-latest'
- }
- })
-
- await waitJobs(servers)
- }
-
- before(async function () {
- this.timeout(240_000)
-
- startTestDate = new Date()
-
- servers = await createMultipleServers(2, getServerImportConfig(mode))
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultChannelAvatar(servers)
- await setDefaultAccountAvatar(servers)
-
- await servers[0].config.enableChannelSync()
-
- {
- userInfo.accessToken = await servers[0].users.generateUserAndToken(userInfo.username)
-
- const { videoChannels } = await servers[0].users.getMyInfo({ token: userInfo.accessToken })
- userInfo.channelId = videoChannels[0].id
- }
-
- sqlCommands = servers.map(s => new SQLCommand(s))
- })
-
- it('Should fetch the latest channel videos of a remote channel', async function () {
- this.timeout(120_000)
-
- {
- const { video } = await servers[0].imports.importVideo({
- attributes: {
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- targetUrl: FIXTURE_URLS.youtube
- }
- })
-
- expect(video.name).to.equal('small video - youtube')
- expect(video.waitTranscoding).to.be.true
-
- const { total } = await listAllVideosOfChannel('root_channel')
- expect(total).to.equal(1)
- }
-
- const { videoChannelSync } = await servers[0].channelSyncs.create({
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- videoChannelId: servers[0].store.channel.id
- }
- })
- rootChannelSyncId = videoChannelSync.id
-
- await forceSyncAll(rootChannelSyncId)
-
- {
- const { total, data } = await listAllVideosOfChannel('root_channel')
- expect(total).to.equal(2)
- expect(data[0].name).to.equal('test')
- expect(data[0].waitTranscoding).to.be.true
- }
- })
-
- it('Should add another synchronization', async function () {
- const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
-
- const { videoChannelSync } = await servers[0].channelSyncs.create({
- attributes: {
- externalChannelUrl,
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
- expect(videoChannelSync.channel.id).to.equal(servers[0].store.channel.id)
- expect(videoChannelSync.channel.name).to.equal('root_channel')
- expect(videoChannelSync.state.id).to.equal(VideoChannelSyncState.WAITING_FIRST_RUN)
- expect(new Date(videoChannelSync.createdAt)).to.be.above(startTestDate).and.to.be.at.most(new Date())
- })
-
- it('Should add a synchronization for another user', async function () {
- const { videoChannelSync } = await servers[0].channelSyncs.create({
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
- videoChannelId: userInfo.channelId
- },
- token: userInfo.accessToken
- })
- userInfo.syncId = videoChannelSync.id
- })
-
- it('Should not import a channel if not asked', async function () {
- await waitJobs(servers)
-
- const { data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
-
- expect(data[0].state).to.contain({
- id: VideoChannelSyncState.WAITING_FIRST_RUN,
- label: 'Waiting first run'
- })
- })
-
- it('Should only fetch the videos newer than the creation date', async function () {
- this.timeout(120_000)
-
- await forceSyncAll(userInfo.syncId, '2019-03-01')
-
- const { data, total } = await listAllVideosOfChannel(userInfo.channelName)
-
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('test')
- })
-
- it('Should list channel synchronizations', async function () {
- // Root
- {
- const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: 'root' })
- expect(total).to.equal(2)
-
- expect(data[0]).to.deep.contain({
- externalChannelUrl: FIXTURE_URLS.youtubeChannel,
- state: {
- id: VideoChannelSyncState.SYNCED,
- label: 'Synchronized'
- }
- })
-
- expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
-
- expect(data[0].channel).to.contain({ id: servers[0].store.channel.id })
- expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
- }
-
- // User
- {
- const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
- expect(total).to.equal(1)
- expect(data[0]).to.deep.contain({
- externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
- state: {
- id: VideoChannelSyncState.SYNCED,
- label: 'Synchronized'
- }
- })
- }
- })
-
- it('Should list imports of a channel synchronization', async function () {
- const { total, data } = await servers[0].imports.getMyVideoImports({ videoChannelSyncId: rootChannelSyncId })
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
- expect(data[0].video.name).to.equal('test')
- })
-
- it('Should remove user\'s channel synchronizations', async function () {
- await servers[0].channelSyncs.delete({ channelSyncId: userInfo.syncId })
-
- const { total } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
- expect(total).to.equal(0)
- })
-
- // FIXME: youtube-dl/yt-dlp doesn't work when speicifying a port after the hostname
- // it('Should import a remote PeerTube channel', async function () {
- // this.timeout(240_000)
-
- // await servers[1].videos.quickUpload({ name: 'remote 1' })
- // await waitJobs(servers)
-
- // const { videoChannelSync } = await servers[0].channelSyncs.create({
- // attributes: {
- // externalChannelUrl: servers[1].url + '/c/root_channel',
- // videoChannelId: userInfo.channelId
- // },
- // token: userInfo.accessToken
- // })
- // await servers[0].channels.importVideos({
- // channelName: userInfo.channelName,
- // externalChannelUrl: servers[1].url + '/c/root_channel',
- // videoChannelSyncId: videoChannelSync.id,
- // token: userInfo.accessToken
- // })
-
- // await waitJobs(servers)
-
- // const { data, total } = await servers[0].videos.listByChannel({
- // handle: userInfo.channelName,
- // include: VideoInclude.NOT_PUBLISHED_STATE
- // })
-
- // expect(total).to.equal(2)
- // expect(data[0].name).to.equal('remote 1')
- // })
-
- // it('Should keep synced a remote PeerTube channel', async function () {
- // this.timeout(240_000)
-
- // await servers[1].videos.quickUpload({ name: 'remote 2' })
- // await waitJobs(servers)
-
- // await servers[0].debug.sendCommand({
- // body: {
- // command: 'process-video-channel-sync-latest'
- // }
- // })
-
- // await waitJobs(servers)
-
- // const { data, total } = await servers[0].videos.listByChannel({
- // handle: userInfo.channelName,
- // include: VideoInclude.NOT_PUBLISHED_STATE
- // })
- // expect(total).to.equal(2)
- // expect(data[0].name).to.equal('remote 2')
- // })
-
- it('Should fetch the latest videos of a youtube playlist', async function () {
- this.timeout(120_000)
-
- const { id: channelId } = await servers[0].channels.create({
- attributes: {
- name: 'channel2'
- }
- })
-
- const { videoChannelSync: { id: videoChannelSyncId } } = await servers[0].channelSyncs.create({
- attributes: {
- externalChannelUrl: FIXTURE_URLS.youtubePlaylist,
- videoChannelId: channelId
- }
- })
-
- await forceSyncAll(videoChannelSyncId)
-
- {
-
- const { total, data } = await listAllVideosOfChannel('channel2')
- expect(total).to.equal(2)
- expect(data[0].name).to.equal('test')
- expect(data[1].name).to.equal('small video - youtube')
- }
- })
-
- after(async function () {
- for (const sqlCommand of sqlCommands) {
- await sqlCommand.cleanup()
- }
-
- await cleanupTests(servers)
- })
- })
- }
-
- // FIXME: suite is broken with youtube-dl
- // runSuite('youtube-dl')
- runSuite('yt-dlp')
-})
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
deleted file mode 100644
index f7cf84618..000000000
--- a/server/tests/api/videos/video-channels.ts
+++ /dev/null
@@ -1,555 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { basename } from 'path'
-import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
-import { SQLCommand, testFileExistsOrNot, testImage } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { ActorImageType, User, VideoChannel } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-async function findChannel (server: PeerTubeServer, channelId: number) {
- const body = await server.channels.list({ sort: '-name' })
-
- return body.data.find(c => c.id === channelId)
-}
-
-describe('Test video channels', function () {
- let servers: PeerTubeServer[]
- let sqlCommands: SQLCommand[] = []
-
- let userInfo: User
- let secondVideoChannelId: number
- let totoChannel: number
- let videoUUID: string
- let accountName: string
- let secondUserChannelName: string
-
- const avatarPaths: { [ port: number ]: string } = {}
- const bannerPaths: { [ port: number ]: string } = {}
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- sqlCommands = servers.map(s => new SQLCommand(s))
- })
-
- it('Should have one video channel (created with root)', async () => {
- const body = await servers[0].channels.list({ start: 0, count: 2 })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- })
-
- it('Should create another video channel', async function () {
- this.timeout(30000)
-
- {
- const videoChannel = {
- name: 'second_video_channel',
- displayName: 'second video channel',
- description: 'super video channel description',
- support: 'super video channel support text'
- }
- const created = await servers[0].channels.create({ attributes: videoChannel })
- secondVideoChannelId = created.id
- }
-
- // The channel is 1 is propagated to servers 2
- {
- const attributes = { name: 'my video name', channelId: secondVideoChannelId, support: 'video support field' }
- const { uuid } = await servers[0].videos.upload({ attributes })
- videoUUID = uuid
- }
-
- await waitJobs(servers)
- })
-
- it('Should have two video channels when getting my information', async () => {
- userInfo = await servers[0].users.getMyInfo()
-
- expect(userInfo.videoChannels).to.be.an('array')
- expect(userInfo.videoChannels).to.have.lengthOf(2)
-
- const videoChannels = userInfo.videoChannels
- expect(videoChannels[0].name).to.equal('root_channel')
- expect(videoChannels[0].displayName).to.equal('Main root channel')
-
- expect(videoChannels[1].name).to.equal('second_video_channel')
- expect(videoChannels[1].displayName).to.equal('second video channel')
- expect(videoChannels[1].description).to.equal('super video channel description')
- expect(videoChannels[1].support).to.equal('super video channel support text')
-
- accountName = userInfo.account.name + '@' + userInfo.account.host
- })
-
- it('Should have two video channels when getting account channels on server 1', async function () {
- const body = await servers[0].channels.listByAccount({ accountName })
- expect(body.total).to.equal(2)
-
- const videoChannels = body.data
-
- expect(videoChannels).to.be.an('array')
- expect(videoChannels).to.have.lengthOf(2)
-
- expect(videoChannels[0].name).to.equal('root_channel')
- expect(videoChannels[0].displayName).to.equal('Main root channel')
-
- expect(videoChannels[1].name).to.equal('second_video_channel')
- expect(videoChannels[1].displayName).to.equal('second video channel')
- expect(videoChannels[1].description).to.equal('super video channel description')
- expect(videoChannels[1].support).to.equal('super video channel support text')
- })
-
- it('Should paginate and sort account channels', async function () {
- {
- const body = await servers[0].channels.listByAccount({
- accountName,
- start: 0,
- count: 1,
- sort: 'createdAt'
- })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(1)
-
- const videoChannel: VideoChannel = body.data[0]
- expect(videoChannel.name).to.equal('root_channel')
- }
-
- {
- const body = await servers[0].channels.listByAccount({
- accountName,
- start: 0,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('second_video_channel')
- }
-
- {
- const body = await servers[0].channels.listByAccount({
- accountName,
- start: 1,
- count: 1,
- sort: '-createdAt'
- })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('root_channel')
- }
- })
-
- it('Should have one video channel when getting account channels on server 2', async function () {
- const body = await servers[1].channels.listByAccount({ accountName })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
-
- const videoChannel = body.data[0]
- expect(videoChannel.name).to.equal('second_video_channel')
- expect(videoChannel.displayName).to.equal('second video channel')
- expect(videoChannel.description).to.equal('super video channel description')
- expect(videoChannel.support).to.equal('super video channel support text')
- })
-
- it('Should list video channels', async function () {
- const body = await servers[0].channels.list({ start: 1, count: 1, sort: '-name' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('root_channel')
- expect(body.data[0].displayName).to.equal('Main root channel')
- })
-
- it('Should update video channel', async function () {
- this.timeout(15000)
-
- const videoChannelAttributes = {
- displayName: 'video channel updated',
- description: 'video channel description updated',
- support: 'support updated'
- }
-
- await servers[0].channels.update({ channelName: 'second_video_channel', attributes: videoChannelAttributes })
-
- await waitJobs(servers)
- })
-
- it('Should have video channel updated', async function () {
- for (const server of servers) {
- const body = await server.channels.list({ start: 0, count: 1, sort: '-name' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
-
- expect(body.data[0].name).to.equal('second_video_channel')
- expect(body.data[0].displayName).to.equal('video channel updated')
- expect(body.data[0].description).to.equal('video channel description updated')
- expect(body.data[0].support).to.equal('support updated')
- }
- })
-
- it('Should not have updated the video support field', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.support).to.equal('video support field')
- }
- })
-
- it('Should update another accounts video channel', async function () {
- this.timeout(15000)
-
- const result = await servers[0].users.generate('second_user')
- secondUserChannelName = result.userChannelName
-
- await servers[0].videos.quickUpload({ name: 'video', token: result.token })
-
- const videoChannelAttributes = {
- displayName: 'video channel updated',
- description: 'video channel description updated',
- support: 'support updated'
- }
-
- await servers[0].channels.update({ channelName: secondUserChannelName, attributes: videoChannelAttributes })
-
- await waitJobs(servers)
- })
-
- it('Should have another accounts video channel updated', async function () {
- for (const server of servers) {
- const body = await server.channels.get({ channelName: `${secondUserChannelName}@${servers[0].host}` })
-
- expect(body.displayName).to.equal('video channel updated')
- expect(body.description).to.equal('video channel description updated')
- expect(body.support).to.equal('support updated')
- }
- })
-
- it('Should update the channel support field and update videos too', async function () {
- this.timeout(35000)
-
- const videoChannelAttributes = {
- support: 'video channel support text updated',
- bulkVideosSupportUpdate: true
- }
-
- await servers[0].channels.update({ channelName: 'second_video_channel', attributes: videoChannelAttributes })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
- expect(video.support).to.equal(videoChannelAttributes.support)
- }
- })
-
- it('Should update video channel avatar', async function () {
- this.timeout(15000)
-
- const fixture = 'avatar.png'
-
- await servers[0].channels.updateImage({
- channelName: 'second_video_channel',
- fixture,
- type: 'avatar'
- })
-
- await waitJobs(servers)
-
- for (let i = 0; i < servers.length; i++) {
- const server = servers[i]
-
- const videoChannel = await findChannel(server, secondVideoChannelId)
- const expectedSizes = ACTOR_IMAGES_SIZE[ActorImageType.AVATAR]
-
- expect(videoChannel.avatars.length).to.equal(expectedSizes.length, 'Expected avatars to be generated in all sizes')
-
- for (const avatar of videoChannel.avatars) {
- avatarPaths[server.port] = avatar.path
- await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatarPaths[server.port], '.png')
- await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), true)
-
- const row = await sqlCommands[i].getActorImage(basename(avatarPaths[server.port]))
-
- expect(expectedSizes.some(({ height, width }) => row.height === height && row.width === width)).to.equal(true)
- }
- }
- })
-
- it('Should update video channel banner', async function () {
- this.timeout(15000)
-
- const fixture = 'banner.jpg'
-
- await servers[0].channels.updateImage({
- channelName: 'second_video_channel',
- fixture,
- type: 'banner'
- })
-
- await waitJobs(servers)
-
- for (let i = 0; i < servers.length; i++) {
- const server = servers[i]
-
- const videoChannel = await server.channels.get({ channelName: 'second_video_channel@' + servers[0].host })
-
- bannerPaths[server.port] = videoChannel.banners[0].path
- await testImage(server.url, 'banner-resized', bannerPaths[server.port])
- await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), true)
-
- const row = await sqlCommands[i].getActorImage(basename(bannerPaths[server.port]))
- expect(row.height).to.equal(ACTOR_IMAGES_SIZE[ActorImageType.BANNER][0].height)
- expect(row.width).to.equal(ACTOR_IMAGES_SIZE[ActorImageType.BANNER][0].width)
- }
- })
-
- it('Should still correctly list channels', async function () {
- {
- const body = await servers[0].channels.list({ start: 1, count: 1, sort: 'createdAt' })
-
- expect(body.total).to.equal(3)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('second_video_channel')
- }
-
- {
- const body = await servers[0].channels.listByAccount({ accountName, start: 1, count: 1, sort: 'createdAt' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.have.lengthOf(1)
- expect(body.data[0].name).to.equal('second_video_channel')
- }
- })
-
- it('Should delete the video channel avatar', async function () {
- this.timeout(15000)
- await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'avatar' })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoChannel = await findChannel(server, secondVideoChannelId)
- await testFileExistsOrNot(server, 'avatars', basename(avatarPaths[server.port]), false)
-
- expect(videoChannel.avatars).to.be.empty
- }
- })
-
- it('Should delete the video channel banner', async function () {
- this.timeout(15000)
-
- await servers[0].channels.deleteImage({ channelName: 'second_video_channel', type: 'banner' })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const videoChannel = await findChannel(server, secondVideoChannelId)
- await testFileExistsOrNot(server, 'avatars', basename(bannerPaths[server.port]), false)
-
- expect(videoChannel.banners).to.be.empty
- }
- })
-
- it('Should list the second video channel videos', async function () {
- for (const server of servers) {
- const channelURI = 'second_video_channel@' + servers[0].host
- const { total, data } = await server.videos.listByChannel({ handle: channelURI })
-
- expect(total).to.equal(1)
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('my video name')
- }
- })
-
- it('Should change the video channel of a video', async function () {
- await servers[0].videos.update({ id: videoUUID, attributes: { channelId: servers[0].store.channel.id } })
-
- await waitJobs(servers)
- })
-
- it('Should list the first video channel videos', async function () {
- for (const server of servers) {
- {
- const secondChannelURI = 'second_video_channel@' + servers[0].host
- const { total } = await server.videos.listByChannel({ handle: secondChannelURI })
- expect(total).to.equal(0)
- }
-
- {
- const channelURI = 'root_channel@' + servers[0].host
- const { total, data } = await server.videos.listByChannel({ handle: channelURI })
- expect(total).to.equal(1)
-
- expect(data).to.be.an('array')
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('my video name')
- }
- }
- })
-
- it('Should delete video channel', async function () {
- await servers[0].channels.delete({ channelName: 'second_video_channel' })
- })
-
- it('Should have video channel deleted', async function () {
- const body = await servers[0].channels.list({ start: 0, count: 10, sort: 'createdAt' })
-
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
- expect(body.data[0].displayName).to.equal('Main root channel')
- expect(body.data[1].displayName).to.equal('video channel updated')
- })
-
- it('Should create the main channel with a suffix if there is a conflict', async function () {
- {
- const videoChannel = { name: 'toto_channel', displayName: 'My toto channel' }
- const created = await servers[0].channels.create({ attributes: videoChannel })
- totoChannel = created.id
- }
-
- {
- await servers[0].users.create({ username: 'toto', password: 'password' })
- const accessToken = await servers[0].login.getAccessToken({ username: 'toto', password: 'password' })
-
- const { videoChannels } = await servers[0].users.getMyInfo({ token: accessToken })
- expect(videoChannels[0].name).to.equal('toto_channel-1')
- }
- })
-
- it('Should report correct channel views per days', async function () {
- {
- const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
-
- for (const channel of data) {
- expect(channel).to.haveOwnProperty('viewsPerDay')
- expect(channel.viewsPerDay).to.have.length(30 + 1) // daysPrior + today
-
- for (const v of channel.viewsPerDay) {
- expect(v.date).to.be.an('string')
- expect(v.views).to.equal(0)
- }
- }
- }
-
- {
- // video has been posted on channel servers[0].store.videoChannel.id since last update
- await servers[0].views.simulateView({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1' })
- await servers[0].views.simulateView({ id: videoUUID, xForwardedFor: '0.0.0.2,127.0.0.1' })
-
- // Wait the repeatable job
- await wait(8000)
-
- const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
- const channelWithView = data.find(channel => channel.id === servers[0].store.channel.id)
- expect(channelWithView.viewsPerDay.slice(-1)[0].views).to.equal(2)
- }
- })
-
- it('Should report correct total views count', async function () {
- // check if there's the property
- {
- const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
-
- for (const channel of data) {
- expect(channel).to.haveOwnProperty('totalViews')
- expect(channel.totalViews).to.be.a('number')
- }
- }
-
- // Check if the totalViews count can be updated
- {
- const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
- const channelWithView = data.find(channel => channel.id === servers[0].store.channel.id)
- expect(channelWithView.totalViews).to.equal(2)
- }
- })
-
- it('Should report correct videos count', async function () {
- const { data } = await servers[0].channels.listByAccount({ accountName, withStats: true })
-
- const totoChannel = data.find(c => c.name === 'toto_channel')
- const rootChannel = data.find(c => c.name === 'root_channel')
-
- expect(rootChannel.videosCount).to.equal(1)
- expect(totoChannel.videosCount).to.equal(0)
- })
-
- it('Should search among account video channels', async function () {
- {
- const body = await servers[0].channels.listByAccount({ accountName, search: 'root' })
- expect(body.total).to.equal(1)
-
- const channels = body.data
- expect(channels).to.have.lengthOf(1)
- }
-
- {
- const body = await servers[0].channels.listByAccount({ accountName, search: 'does not exist' })
- expect(body.total).to.equal(0)
-
- const channels = body.data
- expect(channels).to.have.lengthOf(0)
- }
- })
-
- it('Should list channels by updatedAt desc if a video has been uploaded', async function () {
- this.timeout(30000)
-
- await servers[0].videos.upload({ attributes: { channelId: totoChannel } })
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.channels.listByAccount({ accountName, sort: '-updatedAt' })
-
- expect(data[0].name).to.equal('toto_channel')
- expect(data[1].name).to.equal('root_channel')
- }
-
- await servers[0].videos.upload({ attributes: { channelId: servers[0].store.channel.id } })
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.channels.listByAccount({ accountName, sort: '-updatedAt' })
-
- expect(data[0].name).to.equal('root_channel')
- expect(data[1].name).to.equal('toto_channel')
- }
- })
-
- after(async function () {
- for (const sqlCommand of sqlCommands) {
- await sqlCommand.cleanup()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts
deleted file mode 100644
index b7d5624a6..000000000
--- a/server/tests/api/videos/video-comments.ts
+++ /dev/null
@@ -1,335 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { dateIsValid, testImage } from '@server/tests/shared'
-import {
- cleanupTests,
- CommentsCommand,
- createSingleServer,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar
-} from '@shared/server-commands'
-
-describe('Test video comments', function () {
- let server: PeerTubeServer
- let videoId: number
- let videoUUID: string
- let threadId: number
- let replyToDeleteId: number
-
- let userAccessTokenServer1: string
-
- let command: CommentsCommand
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- const { id, uuid } = await server.videos.upload()
- videoUUID = uuid
- videoId = id
-
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(server)
-
- userAccessTokenServer1 = await server.users.generateUserAndToken('user1')
- await setDefaultChannelAvatar(server, 'user1_channel')
- await setDefaultAccountAvatar(server, userAccessTokenServer1)
-
- command = server.comments
- })
-
- describe('User comments', function () {
-
- it('Should not have threads on this video', async function () {
- const body = await command.listThreads({ videoId: videoUUID })
-
- expect(body.total).to.equal(0)
- expect(body.totalNotDeletedComments).to.equal(0)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should create a thread in this video', async function () {
- const text = 'my super first comment'
-
- const comment = await command.createThread({ videoId: videoUUID, text })
-
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.text).equal('my super first comment')
- expect(comment.videoId).to.equal(videoId)
- expect(comment.id).to.equal(comment.threadId)
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(server.host)
- expect(comment.account.url).to.equal(server.url + '/accounts/root')
- expect(comment.totalReplies).to.equal(0)
- expect(comment.totalRepliesFromVideoAuthor).to.equal(0)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
- })
-
- it('Should list threads of this video', async function () {
- const body = await command.listThreads({ videoId: videoUUID })
-
- expect(body.total).to.equal(1)
- expect(body.totalNotDeletedComments).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
-
- const comment = body.data[0]
- expect(comment.inReplyToCommentId).to.be.null
- expect(comment.text).equal('my super first comment')
- expect(comment.videoId).to.equal(videoId)
- expect(comment.id).to.equal(comment.threadId)
- expect(comment.account.name).to.equal('root')
- expect(comment.account.host).to.equal(server.host)
-
- for (const avatar of comment.account.avatars) {
- await testImage(server.url, `avatar-resized-${avatar.width}x${avatar.width}`, avatar.path, '.png')
- }
-
- expect(comment.totalReplies).to.equal(0)
- expect(comment.totalRepliesFromVideoAuthor).to.equal(0)
- expect(dateIsValid(comment.createdAt as string)).to.be.true
- expect(dateIsValid(comment.updatedAt as string)).to.be.true
-
- threadId = comment.threadId
- })
-
- it('Should get all the thread created', async function () {
- const body = await command.getThread({ videoId: videoUUID, threadId })
-
- const rootComment = body.comment
- expect(rootComment.inReplyToCommentId).to.be.null
- expect(rootComment.text).equal('my super first comment')
- expect(rootComment.videoId).to.equal(videoId)
- expect(dateIsValid(rootComment.createdAt as string)).to.be.true
- expect(dateIsValid(rootComment.updatedAt as string)).to.be.true
- })
-
- it('Should create multiple replies in this thread', async function () {
- const text1 = 'my super answer to thread 1'
- const created = await command.addReply({ videoId, toCommentId: threadId, text: text1 })
- const childCommentId = created.id
-
- const text2 = 'my super answer to answer of thread 1'
- await command.addReply({ videoId, toCommentId: childCommentId, text: text2 })
-
- const text3 = 'my second answer to thread 1'
- await command.addReply({ videoId, toCommentId: threadId, text: text3 })
- })
-
- it('Should get correctly the replies', async function () {
- const tree = await command.getThread({ videoId: videoUUID, threadId })
-
- expect(tree.comment.text).equal('my super first comment')
- expect(tree.children).to.have.lengthOf(2)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('my super answer to thread 1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
- expect(childOfFirstChild.children).to.have.lengthOf(0)
-
- const secondChild = tree.children[1]
- expect(secondChild.comment.text).to.equal('my second answer to thread 1')
- expect(secondChild.children).to.have.lengthOf(0)
-
- replyToDeleteId = secondChild.comment.id
- })
-
- it('Should create other threads', async function () {
- const text1 = 'super thread 2'
- await command.createThread({ videoId: videoUUID, text: text1 })
-
- const text2 = 'super thread 3'
- await command.createThread({ videoId: videoUUID, text: text2 })
- })
-
- it('Should list the threads', async function () {
- const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
-
- expect(body.total).to.equal(3)
- expect(body.totalNotDeletedComments).to.equal(6)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(3)
-
- expect(body.data[0].text).to.equal('my super first comment')
- expect(body.data[0].totalReplies).to.equal(3)
- expect(body.data[1].text).to.equal('super thread 2')
- expect(body.data[1].totalReplies).to.equal(0)
- expect(body.data[2].text).to.equal('super thread 3')
- expect(body.data[2].totalReplies).to.equal(0)
- })
-
- it('Should list the and sort them by total replies', async function () {
- const body = await command.listThreads({ videoId: videoUUID, sort: 'totalReplies' })
-
- expect(body.data[2].text).to.equal('my super first comment')
- expect(body.data[2].totalReplies).to.equal(3)
- })
-
- it('Should delete a reply', async function () {
- await command.delete({ videoId, commentId: replyToDeleteId })
-
- {
- const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
-
- expect(body.total).to.equal(3)
- expect(body.totalNotDeletedComments).to.equal(5)
- }
-
- {
- const tree = await command.getThread({ videoId: videoUUID, threadId })
-
- expect(tree.comment.text).equal('my super first comment')
- expect(tree.children).to.have.lengthOf(2)
-
- const firstChild = tree.children[0]
- expect(firstChild.comment.text).to.equal('my super answer to thread 1')
- expect(firstChild.children).to.have.lengthOf(1)
-
- const childOfFirstChild = firstChild.children[0]
- expect(childOfFirstChild.comment.text).to.equal('my super answer to answer of thread 1')
- expect(childOfFirstChild.children).to.have.lengthOf(0)
-
- const deletedChildOfFirstChild = tree.children[1]
- expect(deletedChildOfFirstChild.comment.text).to.equal('')
- expect(deletedChildOfFirstChild.comment.isDeleted).to.be.true
- expect(deletedChildOfFirstChild.comment.deletedAt).to.not.be.null
- expect(deletedChildOfFirstChild.comment.account).to.be.null
- expect(deletedChildOfFirstChild.children).to.have.lengthOf(0)
- }
- })
-
- it('Should delete a complete thread', async function () {
- await command.delete({ videoId, commentId: threadId })
-
- const body = await command.listThreads({ videoId: videoUUID, sort: 'createdAt' })
- expect(body.total).to.equal(3)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(3)
-
- expect(body.data[0].text).to.equal('')
- expect(body.data[0].isDeleted).to.be.true
- expect(body.data[0].deletedAt).to.not.be.null
- expect(body.data[0].account).to.be.null
- expect(body.data[0].totalReplies).to.equal(2)
- expect(body.data[1].text).to.equal('super thread 2')
- expect(body.data[1].totalReplies).to.equal(0)
- expect(body.data[2].text).to.equal('super thread 3')
- expect(body.data[2].totalReplies).to.equal(0)
- })
-
- it('Should count replies from the video author correctly', async function () {
- await command.createThread({ videoId: videoUUID, text: 'my super first comment' })
-
- const { data } = await command.listThreads({ videoId: videoUUID })
- const threadId2 = data[0].threadId
-
- const text2 = 'a first answer to thread 4 by a third party'
- await command.addReply({ token: userAccessTokenServer1, videoId, toCommentId: threadId2, text: text2 })
-
- const text3 = 'my second answer to thread 4'
- await command.addReply({ videoId, toCommentId: threadId2, text: text3 })
-
- const tree = await command.getThread({ videoId: videoUUID, threadId: threadId2 })
- expect(tree.comment.totalRepliesFromVideoAuthor).to.equal(1)
- expect(tree.comment.totalReplies).to.equal(2)
- })
- })
-
- describe('All instance comments', function () {
-
- it('Should list instance comments as admin', async function () {
- {
- const { data, total } = await command.listForAdmin({ start: 0, count: 1 })
-
- expect(total).to.equal(7)
- expect(data).to.have.lengthOf(1)
- expect(data[0].text).to.equal('my second answer to thread 4')
- expect(data[0].account.name).to.equal('root')
- expect(data[0].account.displayName).to.equal('root')
- expect(data[0].account.avatars).to.have.lengthOf(2)
- }
-
- {
- const { data, total } = await command.listForAdmin({ start: 1, count: 2 })
-
- expect(total).to.equal(7)
- expect(data).to.have.lengthOf(2)
-
- expect(data[0].account.avatars).to.have.lengthOf(2)
- expect(data[1].account.avatars).to.have.lengthOf(2)
- }
- })
-
- it('Should filter instance comments by isLocal', async function () {
- const { total, data } = await command.listForAdmin({ isLocal: false })
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- })
-
- it('Should filter instance comments by onLocalVideo', async function () {
- {
- const { total, data } = await command.listForAdmin({ onLocalVideo: false })
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- }
-
- {
- const { total, data } = await command.listForAdmin({ onLocalVideo: true })
-
- expect(data).to.not.have.lengthOf(0)
- expect(total).to.not.equal(0)
- }
- })
-
- it('Should search instance comments by account', async function () {
- const { total, data } = await command.listForAdmin({ searchAccount: 'user' })
-
- expect(data).to.have.lengthOf(1)
- expect(total).to.equal(1)
-
- expect(data[0].text).to.equal('a first answer to thread 4 by a third party')
- })
-
- it('Should search instance comments by video', async function () {
- {
- const { total, data } = await command.listForAdmin({ searchVideo: 'video' })
-
- expect(data).to.have.lengthOf(7)
- expect(total).to.equal(7)
- }
-
- {
- const { total, data } = await command.listForAdmin({ searchVideo: 'hello' })
-
- expect(data).to.have.lengthOf(0)
- expect(total).to.equal(0)
- }
- })
-
- it('Should search instance comments', async function () {
- const { total, data } = await command.listForAdmin({ search: 'super thread 3' })
-
- expect(total).to.equal(1)
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].text).to.equal('super thread 3')
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/video-description.ts b/server/tests/api/videos/video-description.ts
deleted file mode 100644
index 1f3d4adbb..000000000
--- a/server/tests/api/videos/video-description.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video description', function () {
- let servers: PeerTubeServer[] = []
- let videoUUID = ''
- let videoId: number
-
- const longDescription = 'my super description for server 1'.repeat(50)
-
- // 30 characters * 6 -> 240 characters
- const truncatedDescription = 'my super description for server 1'.repeat(7) + 'my super descrip...'
-
- before(async function () {
- this.timeout(40000)
-
- // Run servers
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should upload video with long description', async function () {
- this.timeout(30000)
-
- const attributes = {
- description: longDescription
- }
- await servers[0].videos.upload({ attributes })
-
- await waitJobs(servers)
-
- const { data } = await servers[0].videos.list()
-
- videoId = data[0].id
- videoUUID = data[0].uuid
- })
-
- it('Should have a truncated description on each server when listing videos', async function () {
- for (const server of servers) {
- const { data } = await server.videos.list()
- const video = data.find(v => v.uuid === videoUUID)
-
- expect(video.description).to.equal(truncatedDescription)
- expect(video.truncatedDescription).to.equal(truncatedDescription)
- }
- })
-
- it('Should not have a truncated description on each server when getting videos', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.description).to.equal(longDescription)
- expect(video.truncatedDescription).to.equal(truncatedDescription)
- }
- })
-
- it('Should fetch long description on each server', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- const { description } = await server.videos.getDescription({ descriptionPath: video.descriptionPath })
- expect(description).to.equal(longDescription)
- }
- })
-
- it('Should update with a short description', async function () {
- const attributes = {
- description: 'short description'
- }
- await servers[0].videos.update({ id: videoId, attributes })
-
- await waitJobs(servers)
- })
-
- it('Should have a small description on each server', async function () {
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.description).to.equal('short description')
-
- const { description } = await server.videos.getDescription({ descriptionPath: video.descriptionPath })
- expect(description).to.equal('short description')
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-files.ts b/server/tests/api/videos/video-files.ts
deleted file mode 100644
index 4f75cd106..000000000
--- a/server/tests/api/videos/video-files.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeRawRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test videos files', function () {
- let servers: PeerTubeServer[]
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(150_000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
- })
-
- describe('When deleting all files', function () {
- let validId1: string
- let validId2: string
-
- before(async function () {
- this.timeout(360_000)
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
- validId1 = uuid
- }
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 2' })
- validId2 = uuid
- }
-
- await waitJobs(servers)
- })
-
- it('Should delete web video files', async function () {
- this.timeout(30_000)
-
- await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1 })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: validId1 })
-
- expect(video.files).to.have.lengthOf(0)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
- }
- })
-
- it('Should delete HLS files', async function () {
- this.timeout(30_000)
-
- await servers[0].videos.removeHLSPlaylist({ videoId: validId2 })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: validId2 })
-
- expect(video.files).to.have.length.above(0)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
- }
- })
- })
-
- describe('When deleting a specific file', function () {
- let webVideoId: string
- let hlsId: string
-
- before(async function () {
- this.timeout(120_000)
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
- webVideoId = uuid
- }
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'hls' })
- hlsId = uuid
- }
-
- await waitJobs(servers)
- })
-
- it('Shoulde delete a web video file', async function () {
- this.timeout(30_000)
-
- const video = await servers[0].videos.get({ id: webVideoId })
- const files = video.files
-
- await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: files[0].id })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: webVideoId })
-
- expect(video.files).to.have.lengthOf(files.length - 1)
- expect(video.files.find(f => f.id === files[0].id)).to.not.exist
- }
- })
-
- it('Should delete all web video files', async function () {
- this.timeout(30_000)
-
- const video = await servers[0].videos.get({ id: webVideoId })
- const files = video.files
-
- for (const file of files) {
- await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: file.id })
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: webVideoId })
-
- expect(video.files).to.have.lengthOf(0)
- }
- })
-
- it('Should delete a hls file', async function () {
- this.timeout(30_000)
-
- const video = await servers[0].videos.get({ id: hlsId })
- const files = video.streamingPlaylists[0].files
- const toDelete = files[0]
-
- await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: toDelete.id })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: hlsId })
-
- expect(video.streamingPlaylists[0].files).to.have.lengthOf(files.length - 1)
- expect(video.streamingPlaylists[0].files.find(f => f.id === toDelete.id)).to.not.exist
-
- const { text } = await makeRawRequest({ url: video.streamingPlaylists[0].playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- expect(text.includes(`-${toDelete.resolution.id}.m3u8`)).to.be.false
- expect(text.includes(`-${video.streamingPlaylists[0].files[0].resolution.id}.m3u8`)).to.be.true
- }
- })
-
- it('Should delete all hls files', async function () {
- this.timeout(30_000)
-
- const video = await servers[0].videos.get({ id: hlsId })
- const files = video.streamingPlaylists[0].files
-
- for (const file of files) {
- await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: file.id })
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: hlsId })
-
- expect(video.streamingPlaylists).to.have.lengthOf(0)
- }
- })
-
- it('Should not delete last file of a video', async function () {
- this.timeout(60_000)
-
- const webVideoOnly = await servers[0].videos.get({ id: hlsId })
- const hlsOnly = await servers[0].videos.get({ id: webVideoId })
-
- for (let i = 0; i < 4; i++) {
- await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[i].id })
- await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[i].id })
- }
-
- const expectedStatus = HttpStatusCode.BAD_REQUEST_400
- await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[4].id, expectedStatus })
- await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[4].id, expectedStatus })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts
deleted file mode 100644
index b78b4f344..000000000
--- a/server/tests/api/videos/video-imports.ts
+++ /dev/null
@@ -1,631 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir, remove } from 'fs-extra'
-import { join } from 'path'
-import { FIXTURE_URLS, testCaptionFile, testImageGeneratedByFFmpeg } from '@server/tests/shared'
-import { areHttpImportTestsDisabled } from '@shared/core-utils'
-import { CustomConfig, HttpStatusCode, Video, VideoImportState, VideoPrivacy, VideoResolution, VideoState } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- createSingleServer,
- doubleFollow,
- getServerImportConfig,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-import { DeepPartial } from '@shared/typescript-utils'
-
-async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) {
- const videoHttp = await server.videos.get({ id: idHttp })
-
- expect(videoHttp.name).to.equal('small video - youtube')
- expect(videoHttp.category.label).to.equal('News & Politics')
- expect(videoHttp.licence.label).to.equal('Attribution')
- expect(videoHttp.language.label).to.equal('Unknown')
- expect(videoHttp.nsfw).to.be.false
- expect(videoHttp.description).to.equal('this is a super description')
- expect(videoHttp.tags).to.deep.equal([ 'tag1', 'tag2' ])
- expect(videoHttp.files).to.have.lengthOf(1)
-
- const originallyPublishedAt = new Date(videoHttp.originallyPublishedAt)
- expect(originallyPublishedAt.getDate()).to.equal(14)
- expect(originallyPublishedAt.getMonth()).to.equal(0)
- expect(originallyPublishedAt.getFullYear()).to.equal(2019)
-
- const videoMagnet = await server.videos.get({ id: idMagnet })
- const videoTorrent = await server.videos.get({ id: idTorrent })
-
- for (const video of [ videoMagnet, videoTorrent ]) {
- expect(video.category.label).to.equal('Unknown')
- expect(video.licence.label).to.equal('Unknown')
- expect(video.language.label).to.equal('Unknown')
- expect(video.nsfw).to.be.false
- expect(video.description).to.equal('this is a super torrent description')
- expect(video.tags).to.deep.equal([ 'tag_torrent1', 'tag_torrent2' ])
- expect(video.files).to.have.lengthOf(1)
- }
-
- expect(videoTorrent.name).to.contain('ä½ å¥½ 世界 720p.mp4')
- expect(videoMagnet.name).to.contain('super peertube2 video')
-
- const bodyCaptions = await server.captions.list({ videoId: idHttp })
- expect(bodyCaptions.total).to.equal(2)
-}
-
-async function checkVideoServer2 (server: PeerTubeServer, id: number | string) {
- const video = await server.videos.get({ id })
-
- expect(video.name).to.equal('my super name')
- expect(video.category.label).to.equal('Entertainment')
- expect(video.licence.label).to.equal('Public Domain Dedication')
- expect(video.language.label).to.equal('English')
- expect(video.nsfw).to.be.false
- expect(video.description).to.equal('my super description')
- expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ])
-
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', video.thumbnailPath)
-
- expect(video.files).to.have.lengthOf(1)
-
- const bodyCaptions = await server.captions.list({ videoId: id })
- expect(bodyCaptions.total).to.equal(2)
-}
-
-describe('Test video imports', function () {
-
- if (areHttpImportTestsDisabled()) return
-
- function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
-
- describe('Import ' + mode, function () {
- let servers: PeerTubeServer[] = []
-
- before(async function () {
- this.timeout(60_000)
-
- servers = await createMultipleServers(2, getServerImportConfig(mode))
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- for (const server of servers) {
- await server.config.updateExistingSubConfig({
- newConfig: {
- transcoding: {
- alwaysTranscodeOriginalResolution: false
- }
- }
- })
- }
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should import videos on server 1', async function () {
- this.timeout(60_000)
-
- const baseAttributes = {
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
-
- {
- const attributes = { ...baseAttributes, targetUrl: FIXTURE_URLS.youtube }
- const { video } = await servers[0].imports.importVideo({ attributes })
- expect(video.name).to.equal('small video - youtube')
-
- {
- expect(video.thumbnailPath).to.match(new RegExp(`^/lazy-static/thumbnails/.+.jpg$`))
- expect(video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`))
-
- const suffix = mode === 'yt-dlp'
- ? '_yt_dlp'
- : ''
-
- await testImageGeneratedByFFmpeg(servers[0].url, 'video_import_thumbnail' + suffix, video.thumbnailPath)
- await testImageGeneratedByFFmpeg(servers[0].url, 'video_import_preview' + suffix, video.previewPath)
- }
-
- const bodyCaptions = await servers[0].captions.list({ videoId: video.id })
- const videoCaptions = bodyCaptions.data
- expect(videoCaptions).to.have.lengthOf(2)
-
- {
- const enCaption = videoCaptions.find(caption => caption.language.id === 'en')
- expect(enCaption).to.exist
- expect(enCaption.language.label).to.equal('English')
- expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`))
-
- const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` +
- `(Language: en[ \n]+)?` +
- `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+English \\(US\\)[ \n]+` +
- `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+This is a subtitle in American English[ \n]+` +
- `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Adding subtitles is very easy to do`
- await testCaptionFile(servers[0].url, enCaption.captionPath, new RegExp(regex))
- }
-
- {
- const frCaption = videoCaptions.find(caption => caption.language.id === 'fr')
- expect(frCaption).to.exist
- expect(frCaption.language.label).to.equal('French')
- expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`))
-
- const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` +
- `(Language: fr[ \n]+)?` +
- `00:00:01.600 --> 00:00:04.200( position:\\d+% line:\\d+%)?[ \n]+Français \\(FR\\)[ \n]+` +
- `00:00:05.900 --> 00:00:07.999( position:\\d+% line:\\d+%)?[ \n]+C'est un sous-titre français[ \n]+` +
- `00:00:10.000 --> 00:00:14.000( position:\\d+% line:\\d+%)?[ \n]+Ajouter un sous-titre est vraiment facile`
-
- await testCaptionFile(servers[0].url, frCaption.captionPath, new RegExp(regex))
- }
- }
-
- {
- const attributes = {
- ...baseAttributes,
- magnetUri: FIXTURE_URLS.magnet,
- description: 'this is a super torrent description',
- tags: [ 'tag_torrent1', 'tag_torrent2' ]
- }
- const { video } = await servers[0].imports.importVideo({ attributes })
- expect(video.name).to.equal('super peertube2 video')
- }
-
- {
- const attributes = {
- ...baseAttributes,
- torrentfile: 'video-720p.torrent' as any,
- description: 'this is a super torrent description',
- tags: [ 'tag_torrent1', 'tag_torrent2' ]
- }
- const { video } = await servers[0].imports.importVideo({ attributes })
- expect(video.name).to.equal('ä½ å¥½ 世界 720p.mp4')
- }
- })
-
- it('Should list the videos to import in my videos on server 1', async function () {
- const { total, data } = await servers[0].videos.listMyVideos({ sort: 'createdAt' })
-
- expect(total).to.equal(3)
-
- expect(data).to.have.lengthOf(3)
- expect(data[0].name).to.equal('small video - youtube')
- expect(data[1].name).to.equal('super peertube2 video')
- expect(data[2].name).to.equal('ä½ å¥½ 世界 720p.mp4')
- })
-
- it('Should list the videos to import in my imports on server 1', async function () {
- const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ sort: '-createdAt' })
- expect(total).to.equal(3)
-
- expect(videoImports).to.have.lengthOf(3)
-
- expect(videoImports[2].targetUrl).to.equal(FIXTURE_URLS.youtube)
- expect(videoImports[2].magnetUri).to.be.null
- expect(videoImports[2].torrentName).to.be.null
- expect(videoImports[2].video.name).to.equal('small video - youtube')
-
- expect(videoImports[1].targetUrl).to.be.null
- expect(videoImports[1].magnetUri).to.equal(FIXTURE_URLS.magnet)
- expect(videoImports[1].torrentName).to.be.null
- expect(videoImports[1].video.name).to.equal('super peertube2 video')
-
- expect(videoImports[0].targetUrl).to.be.null
- expect(videoImports[0].magnetUri).to.be.null
- expect(videoImports[0].torrentName).to.equal('video-720p.torrent')
- expect(videoImports[0].video.name).to.equal('ä½ å¥½ 世界 720p.mp4')
- })
-
- it('Should filter my imports on target URL', async function () {
- const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ targetUrl: FIXTURE_URLS.youtube })
- expect(total).to.equal(1)
- expect(videoImports).to.have.lengthOf(1)
-
- expect(videoImports[0].targetUrl).to.equal(FIXTURE_URLS.youtube)
- })
-
- it('Should search in my imports', async function () {
- const { total, data: videoImports } = await servers[0].imports.getMyVideoImports({ search: 'peertube2' })
- expect(total).to.equal(1)
- expect(videoImports).to.have.lengthOf(1)
-
- expect(videoImports[0].magnetUri).to.equal(FIXTURE_URLS.magnet)
- expect(videoImports[0].video.name).to.equal('super peertube2 video')
- })
-
- it('Should have the video listed on the two instances', async function () {
- this.timeout(120_000)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
-
- const [ videoHttp, videoMagnet, videoTorrent ] = data
- await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
- }
- })
-
- it('Should import a video on server 2 with some fields', async function () {
- this.timeout(60_000)
-
- const { video } = await servers[1].imports.importVideo({
- attributes: {
- targetUrl: FIXTURE_URLS.youtube,
- channelId: servers[1].store.channel.id,
- privacy: VideoPrivacy.PUBLIC,
- category: 10,
- licence: 7,
- language: 'en',
- name: 'my super name',
- description: 'my super description',
- tags: [ 'supertag1', 'supertag2' ],
- thumbnailfile: 'custom-thumbnail.jpg'
- }
- })
- expect(video.name).to.equal('my super name')
- })
-
- it('Should have the videos listed on the two instances', async function () {
- this.timeout(120_000)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(4)
- expect(data).to.have.lengthOf(4)
-
- await checkVideoServer2(server, data[0].uuid)
-
- const [ , videoHttp, videoMagnet, videoTorrent ] = data
- await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
- }
- })
-
- it('Should import a video that will be transcoded', async function () {
- this.timeout(240_000)
-
- const attributes = {
- name: 'transcoded video',
- magnetUri: FIXTURE_URLS.magnet,
- channelId: servers[1].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video } = await servers[1].imports.importVideo({ attributes })
- const videoUUID = video.uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.name).to.equal('transcoded video')
- expect(video.files).to.have.lengthOf(4)
- }
- })
-
- it('Should import no HDR version on a HDR video', async function () {
- this.timeout(300_000)
-
- const config: DeepPartial = {
- transcoding: {
- enabled: true,
- resolutions: {
- '0p': false,
- '144p': true,
- '240p': true,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false, // the resulting resolution shouldn't be higher than this, and not vp9.2/av01
- '1440p': false,
- '2160p': false
- },
- webVideos: { enabled: true },
- hls: { enabled: false }
- }
- }
- await servers[0].config.updateExistingSubConfig({ newConfig: config })
-
- const attributes = {
- name: 'hdr video',
- targetUrl: FIXTURE_URLS.youtubeHDR,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video: videoImported } = await servers[0].imports.importVideo({ attributes })
- const videoUUID = videoImported.uuid
-
- await waitJobs(servers)
-
- // test resolution
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.name).to.equal('hdr video')
- const maxResolution = Math.max.apply(Math, video.files.map(function (o) { return o.resolution.id }))
- expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_240P)
- })
-
- it('Should not import resolution higher than enabled transcoding resolution', async function () {
- this.timeout(300_000)
-
- const config: DeepPartial = {
- transcoding: {
- enabled: true,
- resolutions: {
- '0p': false,
- '144p': true,
- '240p': false,
- '360p': false,
- '480p': false,
- '720p': false,
- '1080p': false,
- '1440p': false,
- '2160p': false
- },
- alwaysTranscodeOriginalResolution: false
- }
- }
- await servers[0].config.updateExistingSubConfig({ newConfig: config })
-
- const attributes = {
- name: 'small resolution video',
- targetUrl: FIXTURE_URLS.youtube,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video: videoImported } = await servers[0].imports.importVideo({ attributes })
- const videoUUID = videoImported.uuid
-
- await waitJobs(servers)
-
- // test resolution
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.name).to.equal('small resolution video')
- expect(video.files).to.have.lengthOf(1)
- expect(video.files[0].resolution.id).to.equal(144)
- })
-
- it('Should import resolution higher than enabled transcoding resolution', async function () {
- this.timeout(300_000)
-
- const config: DeepPartial = {
- transcoding: {
- alwaysTranscodeOriginalResolution: true
- }
- }
- await servers[0].config.updateExistingSubConfig({ newConfig: config })
-
- const attributes = {
- name: 'bigger resolution video',
- targetUrl: FIXTURE_URLS.youtube,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video: videoImported } = await servers[0].imports.importVideo({ attributes })
- const videoUUID = videoImported.uuid
-
- await waitJobs(servers)
-
- // test resolution
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.name).to.equal('bigger resolution video')
-
- expect(video.files).to.have.lengthOf(2)
- expect(video.files.find(f => f.resolution.id === 240)).to.exist
- expect(video.files.find(f => f.resolution.id === 144)).to.exist
- })
-
- it('Should import a peertube video', async function () {
- this.timeout(120_000)
-
- const toTest = [ FIXTURE_URLS.peertube_long ]
-
- // TODO: include peertube_short when https://github.com/ytdl-org/youtube-dl/pull/29475 is merged
- if (mode === 'yt-dlp') {
- toTest.push(FIXTURE_URLS.peertube_short)
- }
-
- for (const targetUrl of toTest) {
- await servers[0].config.disableTranscoding()
-
- const attributes = {
- targetUrl,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video } = await servers[0].imports.importVideo({ attributes })
- const videoUUID = video.uuid
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.name).to.equal('E2E tests')
-
- const { data: captions } = await server.captions.list({ videoId: videoUUID })
- expect(captions).to.have.lengthOf(1)
- expect(captions[0].language.id).to.equal('fr')
-
- const str = `WEBVTT FILE\r?\n\r?\n` +
- `1\r?\n` +
- `00:00:04.000 --> 00:00:09.000\r?\n` +
- `January 1, 1994. The North American`
- await testCaptionFile(server.url, captions[0].captionPath, new RegExp(str))
- }
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
- })
- }
-
- // FIXME: youtube-dl seems broken
- // runSuite('youtube-dl')
-
- runSuite('yt-dlp')
-
- describe('Delete/cancel an import', function () {
- let server: PeerTubeServer
-
- let finishedImportId: number
- let finishedVideo: Video
- let pendingImportId: number
-
- async function importVideo (name: string) {
- const attributes = { name, channelId: server.store.channel.id, targetUrl: FIXTURE_URLS.goodVideo }
- const res = await server.imports.importVideo({ attributes })
-
- return res.id
- }
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- finishedImportId = await importVideo('finished')
- await waitJobs([ server ])
-
- await server.jobs.pauseJobQueue()
- pendingImportId = await importVideo('pending')
-
- const { data } = await server.imports.getMyVideoImports()
- expect(data).to.have.lengthOf(2)
-
- finishedVideo = data.find(i => i.id === finishedImportId).video
- })
-
- it('Should delete a video import', async function () {
- await server.imports.delete({ importId: finishedImportId })
-
- const { data } = await server.imports.getMyVideoImports()
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(pendingImportId)
- expect(data[0].state.id).to.equal(VideoImportState.PENDING)
- })
-
- it('Should not have deleted the associated video', async function () {
- const video = await server.videos.get({ id: finishedVideo.id, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- expect(video.name).to.equal('finished')
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
- })
-
- it('Should cancel a video import', async function () {
- await server.imports.cancel({ importId: pendingImportId })
-
- const { data } = await server.imports.getMyVideoImports()
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(pendingImportId)
- expect(data[0].state.id).to.equal(VideoImportState.CANCELLED)
- })
-
- it('Should not have processed the cancelled video import', async function () {
- this.timeout(60_000)
-
- await server.jobs.resumeJobQueue()
-
- await waitJobs([ server ])
-
- const { data } = await server.imports.getMyVideoImports()
- expect(data).to.have.lengthOf(1)
- expect(data[0].id).to.equal(pendingImportId)
- expect(data[0].state.id).to.equal(VideoImportState.CANCELLED)
- expect(data[0].video.state.id).to.equal(VideoState.TO_IMPORT)
- })
-
- it('Should delete the cancelled video import', async function () {
- await server.imports.delete({ importId: pendingImportId })
- const { data } = await server.imports.getMyVideoImports()
- expect(data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
- })
-
- describe('Auto update', function () {
- let server: PeerTubeServer
-
- function quickPeerTubeImport () {
- const attributes = {
- targetUrl: FIXTURE_URLS.peertube_long,
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
-
- return server.imports.importVideo({ attributes })
- }
-
- async function testBinaryUpdate (releaseUrl: string, releaseName: string) {
- await remove(join(server.servers.buildDirectory('bin'), releaseName))
-
- await server.kill()
- await server.run({
- import: {
- videos: {
- http: {
- youtube_dl_release: {
- url: releaseUrl,
- name: releaseName
- }
- }
- }
- }
- })
-
- await quickPeerTubeImport()
-
- const base = server.servers.buildDirectory('bin')
- const content = await readdir(base)
- const binaryPath = join(base, releaseName)
-
- expect(await pathExists(binaryPath), `${binaryPath} does not exist in ${base} (${content.join(', ')})`).to.be.true
- }
-
- before(async function () {
- this.timeout(30_000)
-
- // Run servers
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
- })
-
- it('Should update youtube-dl from github URL', async function () {
- this.timeout(120_000)
-
- await testBinaryUpdate('https://api.github.com/repos/ytdl-org/youtube-dl/releases', 'youtube-dl')
- })
-
- it('Should update youtube-dl from raw URL', async function () {
- this.timeout(120_000)
-
- await testBinaryUpdate('https://yt-dl.org/downloads/latest/youtube-dl', 'youtube-dl')
- })
-
- it('Should update youtube-dl from youtube-dl fork', async function () {
- this.timeout(120_000)
-
- await testBinaryUpdate('https://api.github.com/repos/yt-dlp/yt-dlp/releases', 'yt-dlp')
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
- })
-})
diff --git a/server/tests/api/videos/video-nsfw.ts b/server/tests/api/videos/video-nsfw.ts
deleted file mode 100644
index 65e9c8730..000000000
--- a/server/tests/api/videos/video-nsfw.ts
+++ /dev/null
@@ -1,227 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-import { BooleanBothQuery, CustomConfig, ResultList, Video, VideosOverview } from '@shared/models'
-
-function createOverviewRes (overview: VideosOverview) {
- const videos = overview.categories[0].videos
- return { data: videos, total: videos.length }
-}
-
-describe('Test video NSFW policy', function () {
- let server: PeerTubeServer
- let userAccessToken: string
- let customConfig: CustomConfig
-
- async function getVideosFunctions (token?: string, query: { nsfw?: BooleanBothQuery } = {}) {
- const user = await server.users.getMyInfo()
-
- const channelName = user.videoChannels[0].name
- const accountName = user.account.name + '@' + user.account.host
-
- const hasQuery = Object.keys(query).length !== 0
- let promises: Promise>[]
-
- if (token) {
- promises = [
- server.search.advancedVideoSearch({ token, search: { search: 'n', sort: '-publishedAt', ...query } }),
- server.videos.listWithToken({ token, ...query }),
- server.videos.listByAccount({ token, handle: accountName, ...query }),
- server.videos.listByChannel({ token, handle: channelName, ...query })
- ]
-
- // Overviews do not support video filters
- if (!hasQuery) {
- const p = server.overviews.getVideos({ page: 1, token })
- .then(res => createOverviewRes(res))
- promises.push(p)
- }
-
- return Promise.all(promises)
- }
-
- promises = [
- server.search.searchVideos({ search: 'n', sort: '-publishedAt' }),
- server.videos.list(),
- server.videos.listByAccount({ token: null, handle: accountName }),
- server.videos.listByChannel({ token: null, handle: channelName })
- ]
-
- // Overviews do not support video filters
- if (!hasQuery) {
- const p = server.overviews.getVideos({ page: 1 })
- .then(res => createOverviewRes(res))
- promises.push(p)
- }
-
- return Promise.all(promises)
- }
-
- before(async function () {
- this.timeout(50000)
- server = await createSingleServer(1)
-
- // Get the access tokens
- await setAccessTokensToServers([ server ])
-
- {
- const attributes = { name: 'nsfw', nsfw: true, category: 1 }
- await server.videos.upload({ attributes })
- }
-
- {
- const attributes = { name: 'normal', nsfw: false, category: 1 }
- await server.videos.upload({ attributes })
- }
-
- customConfig = await server.config.getCustomConfig()
- })
-
- describe('Instance default NSFW policy', function () {
-
- it('Should display NSFW videos with display default NSFW policy', async function () {
- const serverConfig = await server.config.getConfig()
- expect(serverConfig.instance.defaultNSFWPolicy).to.equal('display')
-
- for (const body of await getVideosFunctions()) {
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
- }
- })
-
- it('Should not display NSFW videos with do_not_list default NSFW policy', async function () {
- customConfig.instance.defaultNSFWPolicy = 'do_not_list'
- await server.config.updateCustomConfig({ newCustomConfig: customConfig })
-
- const serverConfig = await server.config.getConfig()
- expect(serverConfig.instance.defaultNSFWPolicy).to.equal('do_not_list')
-
- for (const body of await getVideosFunctions()) {
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('normal')
- }
- })
-
- it('Should display NSFW videos with blur default NSFW policy', async function () {
- customConfig.instance.defaultNSFWPolicy = 'blur'
- await server.config.updateCustomConfig({ newCustomConfig: customConfig })
-
- const serverConfig = await server.config.getConfig()
- expect(serverConfig.instance.defaultNSFWPolicy).to.equal('blur')
-
- for (const body of await getVideosFunctions()) {
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
- }
- })
- })
-
- describe('User NSFW policy', function () {
-
- it('Should create a user having the default nsfw policy', async function () {
- const username = 'user1'
- const password = 'my super password'
- await server.users.create({ username, password })
-
- userAccessToken = await server.login.getAccessToken({ username, password })
-
- const user = await server.users.getMyInfo({ token: userAccessToken })
- expect(user.nsfwPolicy).to.equal('blur')
- })
-
- it('Should display NSFW videos with blur user NSFW policy', async function () {
- customConfig.instance.defaultNSFWPolicy = 'do_not_list'
- await server.config.updateCustomConfig({ newCustomConfig: customConfig })
-
- for (const body of await getVideosFunctions(userAccessToken)) {
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
- }
- })
-
- it('Should display NSFW videos with display user NSFW policy', async function () {
- await server.users.updateMe({ nsfwPolicy: 'display' })
-
- for (const body of await getVideosFunctions(server.accessToken)) {
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
- }
- })
-
- it('Should not display NSFW videos with do_not_list user NSFW policy', async function () {
- await server.users.updateMe({ nsfwPolicy: 'do_not_list' })
-
- for (const body of await getVideosFunctions(server.accessToken)) {
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('normal')
- }
- })
-
- it('Should be able to see my NSFW videos even with do_not_list user NSFW policy', async function () {
- const { total, data } = await server.videos.listMyVideos()
- expect(total).to.equal(2)
-
- expect(data).to.have.lengthOf(2)
- expect(data[0].name).to.equal('normal')
- expect(data[1].name).to.equal('nsfw')
- })
-
- it('Should display NSFW videos when the nsfw param === true', async function () {
- for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'true' })) {
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('nsfw')
- }
- })
-
- it('Should hide NSFW videos when the nsfw param === true', async function () {
- for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'false' })) {
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('normal')
- }
- })
-
- it('Should display both videos when the nsfw param === both', async function () {
- for (const body of await getVideosFunctions(server.accessToken, { nsfw: 'both' })) {
- expect(body.total).to.equal(2)
-
- const videos = body.data
- expect(videos).to.have.lengthOf(2)
- expect(videos[0].name).to.equal('normal')
- expect(videos[1].name).to.equal('nsfw')
- }
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/video-passwords.ts b/server/tests/api/videos/video-passwords.ts
deleted file mode 100644
index e01a93a4d..000000000
--- a/server/tests/api/videos/video-passwords.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- VideoPasswordsCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar
-} from '@shared/server-commands'
-import { VideoPrivacy } from '@shared/models'
-
-describe('Test video passwords', function () {
- let server: PeerTubeServer
- let videoUUID: string
-
- let userAccessTokenServer1: string
-
- let videoPasswords: string[] = []
- let command: VideoPasswordsCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- for (let i = 0; i < 10; i++) {
- videoPasswords.push(`password ${i + 1}`)
- }
- const { uuid } = await server.videos.upload({ attributes: { privacy: VideoPrivacy.PASSWORD_PROTECTED, videoPasswords } })
- videoUUID = uuid
-
- await setDefaultChannelAvatar(server)
- await setDefaultAccountAvatar(server)
-
- userAccessTokenServer1 = await server.users.generateUserAndToken('user1')
- await setDefaultChannelAvatar(server, 'user1_channel')
- await setDefaultAccountAvatar(server, userAccessTokenServer1)
-
- command = server.videoPasswords
- })
-
- it('Should list video passwords', async function () {
- const body = await command.list({ videoId: videoUUID })
-
- expect(body.total).to.equal(10)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(10)
- })
-
- it('Should filter passwords on this video', async function () {
- const body = await command.list({ videoId: videoUUID, count: 2, start: 3, sort: 'createdAt' })
-
- expect(body.total).to.equal(10)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
- expect(body.data[0].password).to.equal('password 4')
- expect(body.data[1].password).to.equal('password 5')
- })
-
- it('Should update password for this video', async function () {
- videoPasswords = [ 'my super new password 1', 'my super new password 2' ]
-
- await command.updateAll({ videoId: videoUUID, passwords: videoPasswords })
- const body = await command.list({ videoId: videoUUID })
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
- expect(body.data[0].password).to.equal('my super new password 2')
- expect(body.data[1].password).to.equal('my super new password 1')
- })
-
- it('Should delete one password', async function () {
- {
- const body = await command.list({ videoId: videoUUID })
- expect(body.total).to.equal(2)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(2)
- await command.remove({ id: body.data[0].id, videoId: videoUUID })
- }
- {
- const body = await command.list({ videoId: videoUUID })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.be.an('array')
- expect(body.data).to.have.lengthOf(1)
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/video-playlist-thumbnails.ts b/server/tests/api/videos/video-playlist-thumbnails.ts
deleted file mode 100644
index c274c20bf..000000000
--- a/server/tests/api/videos/video-playlist-thumbnails.ts
+++ /dev/null
@@ -1,234 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { testImageGeneratedByFFmpeg } from '@server/tests/shared'
-import { VideoPlaylistPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Playlist thumbnail', function () {
- let servers: PeerTubeServer[] = []
-
- let playlistWithoutThumbnailId: number
- let playlistWithThumbnailId: number
-
- let withThumbnailE1: number
- let withThumbnailE2: number
- let withoutThumbnailE1: number
- let withoutThumbnailE2: number
-
- let video1: number
- let video2: number
-
- async function getPlaylistWithoutThumbnail (server: PeerTubeServer) {
- const body = await server.playlists.list({ start: 0, count: 10 })
-
- return body.data.find(p => p.displayName === 'playlist without thumbnail')
- }
-
- async function getPlaylistWithThumbnail (server: PeerTubeServer) {
- const body = await server.playlists.list({ start: 0, count: 10 })
-
- return body.data.find(p => p.displayName === 'playlist with thumbnail')
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- for (const server of servers) {
- await server.config.disableTranscoding()
- }
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
-
- video1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).id
- video2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).id
-
- await waitJobs(servers)
- })
-
- it('Should automatically update the thumbnail when adding an element', async function () {
- this.timeout(30000)
-
- const created = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist without thumbnail',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].store.channel.id
- }
- })
- playlistWithoutThumbnailId = created.id
-
- const added = await servers[1].playlists.addElement({
- playlistId: playlistWithoutThumbnailId,
- attributes: { videoId: video1 }
- })
- withoutThumbnailE1 = added.id
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithoutThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath)
- }
- })
-
- it('Should not update the thumbnail if we explicitly uploaded a thumbnail', async function () {
- this.timeout(30000)
-
- const created = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist with thumbnail',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].store.channel.id,
- thumbnailfile: 'custom-thumbnail.jpg'
- }
- })
- playlistWithThumbnailId = created.id
-
- const added = await servers[1].playlists.addElement({
- playlistId: playlistWithThumbnailId,
- attributes: { videoId: video1 }
- })
- withThumbnailE1 = added.id
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath)
- }
- })
-
- it('Should automatically update the thumbnail when moving the first element', async function () {
- this.timeout(30000)
-
- const added = await servers[1].playlists.addElement({
- playlistId: playlistWithoutThumbnailId,
- attributes: { videoId: video2 }
- })
- withoutThumbnailE2 = added.id
-
- await servers[1].playlists.reorderElements({
- playlistId: playlistWithoutThumbnailId,
- attributes: {
- startPosition: 1,
- insertAfterPosition: 2
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithoutThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath)
- }
- })
-
- it('Should not update the thumbnail when moving the first element if we explicitly uploaded a thumbnail', async function () {
- this.timeout(30000)
-
- const added = await servers[1].playlists.addElement({
- playlistId: playlistWithThumbnailId,
- attributes: { videoId: video2 }
- })
- withThumbnailE2 = added.id
-
- await servers[1].playlists.reorderElements({
- playlistId: playlistWithThumbnailId,
- attributes: {
- startPosition: 1,
- insertAfterPosition: 2
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath)
- }
- })
-
- it('Should automatically update the thumbnail when deleting the first element', async function () {
- this.timeout(30000)
-
- await servers[1].playlists.removeElement({
- playlistId: playlistWithoutThumbnailId,
- elementId: withoutThumbnailE1
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithoutThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', p.thumbnailPath)
- }
- })
-
- it('Should not update the thumbnail when deleting the first element if we explicitly uploaded a thumbnail', async function () {
- this.timeout(30000)
-
- await servers[1].playlists.removeElement({
- playlistId: playlistWithThumbnailId,
- elementId: withThumbnailE1
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath)
- }
- })
-
- it('Should the thumbnail when we delete the last element', async function () {
- this.timeout(30000)
-
- await servers[1].playlists.removeElement({
- playlistId: playlistWithoutThumbnailId,
- elementId: withoutThumbnailE2
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithoutThumbnail(server)
- expect(p.thumbnailPath).to.be.null
- }
- })
-
- it('Should not update the thumbnail when we delete the last element if we explicitly uploaded a thumbnail', async function () {
- this.timeout(30000)
-
- await servers[1].playlists.removeElement({
- playlistId: playlistWithThumbnailId,
- elementId: withThumbnailE2
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const p = await getPlaylistWithThumbnail(server)
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', p.thumbnailPath)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
deleted file mode 100644
index 3bfa874cb..000000000
--- a/server/tests/api/videos/video-playlists.ts
+++ /dev/null
@@ -1,1208 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { checkPlaylistFilesWereRemoved, testImageGeneratedByFFmpeg } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { uuidToShort } from '@shared/extra-utils'
-import {
- HttpStatusCode,
- VideoPlaylist,
- VideoPlaylistCreateResult,
- VideoPlaylistElementType,
- VideoPlaylistPrivacy,
- VideoPlaylistType,
- VideoPrivacy
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- PlaylistsCommand,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkPlaylistElementType (
- servers: PeerTubeServer[],
- playlistId: string,
- type: VideoPlaylistElementType,
- position: number,
- name: string,
- total: number
-) {
- for (const server of servers) {
- const body = await server.playlists.listVideos({ token: server.accessToken, playlistId, start: 0, count: 10 })
- expect(body.total).to.equal(total)
-
- const videoElement = body.data.find(e => e.position === position)
- expect(videoElement.type).to.equal(type, 'On server ' + server.url)
-
- if (type === VideoPlaylistElementType.REGULAR) {
- expect(videoElement.video).to.not.be.null
- expect(videoElement.video.name).to.equal(name)
- } else {
- expect(videoElement.video).to.be.null
- }
- }
-}
-
-describe('Test video playlists', function () {
- let servers: PeerTubeServer[] = []
-
- let playlistServer2Id1: number
- let playlistServer2Id2: number
- let playlistServer2UUID2: string
-
- let playlistServer1Id: number
- let playlistServer1DisplayName: string
- let playlistServer1UUID: string
- let playlistServer1UUID2: string
-
- let playlistElementServer1Video4: number
- let playlistElementServer1Video5: number
- let playlistElementNSFW: number
-
- let nsfwVideoServer1: number
-
- let userTokenServer1: string
-
- let commands: PlaylistsCommand[]
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(3)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- for (const server of servers) {
- await server.config.disableTranscoding()
- }
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- // Server 1 and server 3 follow each other
- await doubleFollow(servers[0], servers[2])
-
- commands = servers.map(s => s.playlists)
-
- {
- servers[0].store.videos = []
- servers[1].store.videos = []
- servers[2].store.videos = []
-
- for (const server of servers) {
- for (let i = 0; i < 7; i++) {
- const name = `video ${i} server ${server.serverNumber}`
- const video = await server.videos.upload({ attributes: { name, nsfw: false } })
-
- server.store.videos.push(video)
- }
- }
- }
-
- nsfwVideoServer1 = (await servers[0].videos.quickUpload({ name: 'NSFW video', nsfw: true })).id
-
- userTokenServer1 = await servers[0].users.generateUserAndToken('user1')
-
- await waitJobs(servers)
- })
-
- describe('Check playlists filters and privacies', function () {
-
- it('Should list video playlist privacies', async function () {
- const privacies = await commands[0].getPrivacies()
-
- expect(Object.keys(privacies)).to.have.length.at.least(3)
- expect(privacies[3]).to.equal('Private')
- })
-
- it('Should filter on playlist type', async function () {
- this.timeout(30000)
-
- const token = servers[0].accessToken
-
- await commands[0].create({
- attributes: {
- displayName: 'my super playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- description: 'my super description',
- thumbnailfile: 'custom-thumbnail.jpg',
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- {
- const body = await commands[0].listByAccount({ token, handle: 'root', playlistType: VideoPlaylistType.WATCH_LATER })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlist = body.data[0]
- expect(playlist.displayName).to.equal('Watch later')
- expect(playlist.type.id).to.equal(VideoPlaylistType.WATCH_LATER)
- expect(playlist.type.label).to.equal('Watch later')
- expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
- }
-
- {
- const bodyList = await commands[0].list({ playlistType: VideoPlaylistType.WATCH_LATER })
- const bodyChannel = await commands[0].listByChannel({ handle: 'root_channel', playlistType: VideoPlaylistType.WATCH_LATER })
-
- for (const body of [ bodyList, bodyChannel ]) {
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- }
-
- {
- const bodyList = await commands[0].list({ playlistType: VideoPlaylistType.REGULAR })
- const bodyChannel = await commands[0].listByChannel({ handle: 'root_channel', playlistType: VideoPlaylistType.REGULAR })
-
- let playlist: VideoPlaylist = null
- for (const body of [ bodyList, bodyChannel ]) {
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- playlist = body.data[0]
- expect(playlist.displayName).to.equal('my super playlist')
- expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.PUBLIC)
- expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
- }
-
- await commands[0].update({
- playlistId: playlist.id,
- attributes: {
- privacy: VideoPlaylistPrivacy.PRIVATE
- }
- })
- }
-
- {
- const bodyList = await commands[0].list({ playlistType: VideoPlaylistType.REGULAR })
- const bodyChannel = await commands[0].listByChannel({ handle: 'root_channel', playlistType: VideoPlaylistType.REGULAR })
-
- for (const body of [ bodyList, bodyChannel ]) {
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- }
-
- {
- const body = await commands[0].listByAccount({ handle: 'root' })
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- }
- })
-
- it('Should get private playlist for a classic user', async function () {
- const token = await servers[0].users.generateUserAndToken('toto')
-
- const body = await commands[0].listByAccount({ token, handle: 'toto' })
-
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlistId = body.data[0].id
- await commands[0].listVideos({ token, playlistId })
- })
- })
-
- describe('Create and federate playlists', function () {
-
- it('Should create a playlist on server 1 and have the playlist on server 2 and 3', async function () {
- this.timeout(30000)
-
- await commands[0].create({
- attributes: {
- displayName: 'my super playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- description: 'my super description',
- thumbnailfile: 'custom-thumbnail.jpg',
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- await waitJobs(servers)
- // Processing a playlist by the receiver could be long
- await wait(3000)
-
- for (const server of servers) {
- const body = await server.playlists.list({ start: 0, count: 5 })
- expect(body.total).to.equal(1)
- expect(body.data).to.have.lengthOf(1)
-
- const playlistFromList = body.data[0]
-
- const playlistFromGet = await server.playlists.get({ playlistId: playlistFromList.uuid })
-
- for (const playlist of [ playlistFromGet, playlistFromList ]) {
- expect(playlist.id).to.be.a('number')
- expect(playlist.uuid).to.be.a('string')
-
- expect(playlist.isLocal).to.equal(server.serverNumber === 1)
-
- expect(playlist.displayName).to.equal('my super playlist')
- expect(playlist.description).to.equal('my super description')
- expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.PUBLIC)
- expect(playlist.privacy.label).to.equal('Public')
- expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
- expect(playlist.type.label).to.equal('Regular')
- expect(playlist.embedPath).to.equal('/video-playlists/embed/' + playlist.uuid)
-
- expect(playlist.videosLength).to.equal(0)
-
- expect(playlist.ownerAccount.name).to.equal('root')
- expect(playlist.ownerAccount.displayName).to.equal('root')
- expect(playlist.videoChannel.name).to.equal('root_channel')
- expect(playlist.videoChannel.displayName).to.equal('Main root channel')
- }
- }
- })
-
- it('Should create a playlist on server 2 and have the playlist on server 1 but not on server 3', async function () {
- this.timeout(30000)
-
- {
- const playlist = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist 2',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[1].store.channel.id
- }
- })
- playlistServer2Id1 = playlist.id
- }
-
- {
- const playlist = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist 3',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- thumbnailfile: 'custom-thumbnail.jpg',
- videoChannelId: servers[1].store.channel.id
- }
- })
-
- playlistServer2Id2 = playlist.id
- playlistServer2UUID2 = playlist.uuid
- }
-
- for (const id of [ playlistServer2Id1, playlistServer2Id2 ]) {
- await servers[1].playlists.addElement({
- playlistId: id,
- attributes: { videoId: servers[1].store.videos[0].id, startTimestamp: 1, stopTimestamp: 2 }
- })
- await servers[1].playlists.addElement({
- playlistId: id,
- attributes: { videoId: servers[1].store.videos[1].id }
- })
- }
-
- await waitJobs(servers)
- await wait(3000)
-
- for (const server of [ servers[0], servers[1] ]) {
- const body = await server.playlists.list({ start: 0, count: 5 })
-
- const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
- expect(playlist2).to.not.be.undefined
- await testImageGeneratedByFFmpeg(server.url, 'thumbnail-playlist', playlist2.thumbnailPath)
-
- const playlist3 = body.data.find(p => p.displayName === 'playlist 3')
- expect(playlist3).to.not.be.undefined
- await testImageGeneratedByFFmpeg(server.url, 'custom-thumbnail', playlist3.thumbnailPath)
- }
-
- const body = await servers[2].playlists.list({ start: 0, count: 5 })
- expect(body.data.find(p => p.displayName === 'playlist 2')).to.be.undefined
- expect(body.data.find(p => p.displayName === 'playlist 3')).to.be.undefined
- })
-
- it('Should have the playlist on server 3 after a new follow', async function () {
- this.timeout(30000)
-
- // Server 2 and server 3 follow each other
- await doubleFollow(servers[1], servers[2])
-
- const body = await servers[2].playlists.list({ start: 0, count: 5 })
-
- const playlist2 = body.data.find(p => p.displayName === 'playlist 2')
- expect(playlist2).to.not.be.undefined
- await testImageGeneratedByFFmpeg(servers[2].url, 'thumbnail-playlist', playlist2.thumbnailPath)
-
- expect(body.data.find(p => p.displayName === 'playlist 3')).to.not.be.undefined
- })
- })
-
- describe('List playlists', function () {
-
- it('Should correctly list the playlists', async function () {
- this.timeout(30000)
-
- {
- const body = await servers[2].playlists.list({ start: 1, count: 2, sort: 'createdAt' })
- expect(body.total).to.equal(3)
-
- const data = body.data
- expect(data).to.have.lengthOf(2)
- expect(data[0].displayName).to.equal('playlist 2')
- expect(data[1].displayName).to.equal('playlist 3')
- }
-
- {
- const body = await servers[2].playlists.list({ start: 1, count: 2, sort: '-createdAt' })
- expect(body.total).to.equal(3)
-
- const data = body.data
- expect(data).to.have.lengthOf(2)
- expect(data[0].displayName).to.equal('playlist 2')
- expect(data[1].displayName).to.equal('my super playlist')
- }
- })
-
- it('Should list video channel playlists', async function () {
- this.timeout(30000)
-
- {
- const body = await commands[0].listByChannel({ handle: 'root_channel', start: 0, count: 2, sort: '-createdAt' })
- expect(body.total).to.equal(1)
-
- const data = body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].displayName).to.equal('my super playlist')
- }
- })
-
- it('Should list account playlists', async function () {
- this.timeout(30000)
-
- {
- const body = await servers[1].playlists.listByAccount({ handle: 'root', start: 1, count: 2, sort: '-createdAt' })
- expect(body.total).to.equal(2)
-
- const data = body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].displayName).to.equal('playlist 2')
- }
-
- {
- const body = await servers[1].playlists.listByAccount({ handle: 'root', start: 1, count: 2, sort: 'createdAt' })
- expect(body.total).to.equal(2)
-
- const data = body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].displayName).to.equal('playlist 3')
- }
-
- {
- const body = await servers[1].playlists.listByAccount({ handle: 'root', sort: 'createdAt', search: '3' })
- expect(body.total).to.equal(1)
-
- const data = body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].displayName).to.equal('playlist 3')
- }
-
- {
- const body = await servers[1].playlists.listByAccount({ handle: 'root', sort: 'createdAt', search: '4' })
- expect(body.total).to.equal(0)
-
- const data = body.data
- expect(data).to.have.lengthOf(0)
- }
- })
- })
-
- describe('Playlist rights', function () {
- let unlistedPlaylist: VideoPlaylistCreateResult
- let privatePlaylist: VideoPlaylistCreateResult
-
- before(async function () {
- this.timeout(30000)
-
- {
- unlistedPlaylist = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist unlisted',
- privacy: VideoPlaylistPrivacy.UNLISTED,
- videoChannelId: servers[1].store.channel.id
- }
- })
- }
-
- {
- privatePlaylist = await servers[1].playlists.create({
- attributes: {
- displayName: 'playlist private',
- privacy: VideoPlaylistPrivacy.PRIVATE
- }
- })
- }
-
- await waitJobs(servers)
- await wait(3000)
- })
-
- it('Should not list unlisted or private playlists', async function () {
- for (const server of servers) {
- const results = [
- await server.playlists.listByAccount({ handle: 'root@' + servers[1].host, sort: '-createdAt' }),
- await server.playlists.list({ start: 0, count: 2, sort: '-createdAt' })
- ]
-
- expect(results[0].total).to.equal(2)
- expect(results[1].total).to.equal(3)
-
- for (const body of results) {
- const data = body.data
- expect(data).to.have.lengthOf(2)
- expect(data[0].displayName).to.equal('playlist 3')
- expect(data[1].displayName).to.equal('playlist 2')
- }
- }
- })
-
- it('Should not get unlisted playlist using only the id', async function () {
- await servers[1].playlists.get({ playlistId: unlistedPlaylist.id, expectedStatus: 404 })
- })
-
- it('Should get unlisted playlist using uuid or shortUUID', async function () {
- await servers[1].playlists.get({ playlistId: unlistedPlaylist.uuid })
- await servers[1].playlists.get({ playlistId: unlistedPlaylist.shortUUID })
- })
-
- it('Should not get private playlist without token', async function () {
- for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
- await servers[1].playlists.get({ playlistId: id, expectedStatus: 401 })
- }
- })
-
- it('Should get private playlist with a token', async function () {
- for (const id of [ privatePlaylist.id, privatePlaylist.uuid, privatePlaylist.shortUUID ]) {
- await servers[1].playlists.get({ token: servers[1].accessToken, playlistId: id })
- }
- })
- })
-
- describe('Update playlists', function () {
-
- it('Should update a playlist', async function () {
- this.timeout(30000)
-
- await servers[1].playlists.update({
- attributes: {
- displayName: 'playlist 3 updated',
- description: 'description updated',
- privacy: VideoPlaylistPrivacy.UNLISTED,
- thumbnailfile: 'custom-thumbnail.jpg',
- videoChannelId: servers[1].store.channel.id
- },
- playlistId: playlistServer2Id2
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const playlist = await server.playlists.get({ playlistId: playlistServer2UUID2 })
-
- expect(playlist.displayName).to.equal('playlist 3 updated')
- expect(playlist.description).to.equal('description updated')
-
- expect(playlist.privacy.id).to.equal(VideoPlaylistPrivacy.UNLISTED)
- expect(playlist.privacy.label).to.equal('Unlisted')
-
- expect(playlist.type.id).to.equal(VideoPlaylistType.REGULAR)
- expect(playlist.type.label).to.equal('Regular')
-
- expect(playlist.videosLength).to.equal(2)
-
- expect(playlist.ownerAccount.name).to.equal('root')
- expect(playlist.ownerAccount.displayName).to.equal('root')
- expect(playlist.videoChannel.name).to.equal('root_channel')
- expect(playlist.videoChannel.displayName).to.equal('Main root channel')
- }
- })
- })
-
- describe('Element timestamps', function () {
-
- it('Should create a playlist containing different startTimestamp/endTimestamp videos', async function () {
- this.timeout(30000)
-
- const addVideo = (attributes: any) => {
- return commands[0].addElement({ playlistId: playlistServer1Id, attributes })
- }
-
- const playlistDisplayName = 'playlist 4'
- const playlist = await commands[0].create({
- attributes: {
- displayName: playlistDisplayName,
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- playlistServer1Id = playlist.id
- playlistServer1DisplayName = playlistDisplayName
- playlistServer1UUID = playlist.uuid
-
- await addVideo({ videoId: servers[0].store.videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
- await addVideo({ videoId: servers[2].store.videos[1].uuid, startTimestamp: 35 })
- await addVideo({ videoId: servers[2].store.videos[2].uuid })
- {
- const element = await addVideo({ videoId: servers[0].store.videos[3].uuid, stopTimestamp: 35 })
- playlistElementServer1Video4 = element.id
- }
-
- {
- const element = await addVideo({ videoId: servers[0].store.videos[4].uuid, startTimestamp: 45, stopTimestamp: 60 })
- playlistElementServer1Video5 = element.id
- }
-
- {
- const element = await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 5 })
- playlistElementNSFW = element.id
-
- await addVideo({ videoId: nsfwVideoServer1, startTimestamp: 4 })
- await addVideo({ videoId: nsfwVideoServer1 })
- }
-
- await waitJobs(servers)
- })
-
- it('Should correctly list playlist videos', async function () {
- this.timeout(30000)
-
- for (const server of servers) {
- {
- const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
-
- expect(body.total).to.equal(8)
-
- const videoElements = body.data
- expect(videoElements).to.have.lengthOf(8)
-
- expect(videoElements[0].video.name).to.equal('video 0 server 1')
- expect(videoElements[0].position).to.equal(1)
- expect(videoElements[0].startTimestamp).to.equal(15)
- expect(videoElements[0].stopTimestamp).to.equal(28)
-
- expect(videoElements[1].video.name).to.equal('video 1 server 3')
- expect(videoElements[1].position).to.equal(2)
- expect(videoElements[1].startTimestamp).to.equal(35)
- expect(videoElements[1].stopTimestamp).to.be.null
-
- expect(videoElements[2].video.name).to.equal('video 2 server 3')
- expect(videoElements[2].position).to.equal(3)
- expect(videoElements[2].startTimestamp).to.be.null
- expect(videoElements[2].stopTimestamp).to.be.null
-
- expect(videoElements[3].video.name).to.equal('video 3 server 1')
- expect(videoElements[3].position).to.equal(4)
- expect(videoElements[3].startTimestamp).to.be.null
- expect(videoElements[3].stopTimestamp).to.equal(35)
-
- expect(videoElements[4].video.name).to.equal('video 4 server 1')
- expect(videoElements[4].position).to.equal(5)
- expect(videoElements[4].startTimestamp).to.equal(45)
- expect(videoElements[4].stopTimestamp).to.equal(60)
-
- expect(videoElements[5].video.name).to.equal('NSFW video')
- expect(videoElements[5].position).to.equal(6)
- expect(videoElements[5].startTimestamp).to.equal(5)
- expect(videoElements[5].stopTimestamp).to.be.null
-
- expect(videoElements[6].video.name).to.equal('NSFW video')
- expect(videoElements[6].position).to.equal(7)
- expect(videoElements[6].startTimestamp).to.equal(4)
- expect(videoElements[6].stopTimestamp).to.be.null
-
- expect(videoElements[7].video.name).to.equal('NSFW video')
- expect(videoElements[7].position).to.equal(8)
- expect(videoElements[7].startTimestamp).to.be.null
- expect(videoElements[7].stopTimestamp).to.be.null
- }
-
- {
- const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 2 })
- expect(body.data).to.have.lengthOf(2)
- }
- }
- })
- })
-
- describe('Element type', function () {
- let groupUser1: PeerTubeServer[]
- let groupWithoutToken1: PeerTubeServer[]
- let group1: PeerTubeServer[]
- let group2: PeerTubeServer[]
-
- let video1: string
- let video2: string
- let video3: string
-
- before(async function () {
- this.timeout(60000)
-
- groupUser1 = [ Object.assign({}, servers[0], { accessToken: userTokenServer1 }) ]
- groupWithoutToken1 = [ Object.assign({}, servers[0], { accessToken: undefined }) ]
- group1 = [ servers[0] ]
- group2 = [ servers[1], servers[2] ]
-
- const playlist = await commands[0].create({
- token: userTokenServer1,
- attributes: {
- displayName: 'playlist 56',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- const playlistServer1Id2 = playlist.id
- playlistServer1UUID2 = playlist.uuid
-
- const addVideo = (attributes: any) => {
- return commands[0].addElement({ token: userTokenServer1, playlistId: playlistServer1Id2, attributes })
- }
-
- video1 = (await servers[0].videos.quickUpload({ name: 'video 89', token: userTokenServer1 })).uuid
- video2 = (await servers[1].videos.quickUpload({ name: 'video 90' })).uuid
- video3 = (await servers[0].videos.quickUpload({ name: 'video 91', nsfw: true })).uuid
-
- await waitJobs(servers)
-
- await addVideo({ videoId: video1, startTimestamp: 15, stopTimestamp: 28 })
- await addVideo({ videoId: video2, startTimestamp: 35 })
- await addVideo({ videoId: video3 })
-
- await waitJobs(servers)
- })
-
- it('Should update the element type if the video is private/password protected', async function () {
- this.timeout(20000)
-
- const name = 'video 89'
- const position = 1
-
- {
- await servers[0].videos.update({ id: video1, attributes: { privacy: VideoPrivacy.PRIVATE } })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
- await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
- }
-
- {
- await servers[0].videos.update({
- id: video1,
- attributes: { privacy: VideoPrivacy.PASSWORD_PROTECTED, videoPasswords: [ 'password' ] }
- })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
- await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.PRIVATE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
- }
-
- {
- await servers[0].videos.update({ id: video1, attributes: { privacy: VideoPrivacy.PUBLIC } })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- // We deleted the video, so even if we recreated it, the old entry is still deleted
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
- }
- })
-
- it('Should update the element type if the video is blacklisted', async function () {
- this.timeout(20000)
-
- const name = 'video 89'
- const position = 1
-
- {
- await servers[0].blacklist.add({ videoId: video1, reason: 'reason', unfederate: true })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
- }
-
- {
- await servers[0].blacklist.remove({ videoId: video1 })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(groupWithoutToken1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- await checkPlaylistElementType(group1, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- // We deleted the video (because unfederated), so even if we recreated it, the old entry is still deleted
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.DELETED, position, name, 3)
- }
- })
-
- it('Should update the element type if the account or server of the video is blocked', async function () {
- this.timeout(90000)
-
- const command = servers[0].blocklist
-
- const name = 'video 90'
- const position = 2
-
- {
- await command.addToMyBlocklist({ token: userTokenServer1, account: 'root@' + servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
-
- await command.removeFromMyBlocklist({ token: userTokenServer1, account: 'root@' + servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- }
-
- {
- await command.addToMyBlocklist({ token: userTokenServer1, server: servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
-
- await command.removeFromMyBlocklist({ token: userTokenServer1, server: servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- }
-
- {
- await command.addToServerBlocklist({ account: 'root@' + servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
-
- await command.removeFromServerBlocklist({ account: 'root@' + servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- }
-
- {
- await command.addToServerBlocklist({ server: servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(groupUser1, playlistServer1UUID2, VideoPlaylistElementType.UNAVAILABLE, position, name, 3)
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
-
- await command.removeFromServerBlocklist({ server: servers[1].host })
- await waitJobs(servers)
-
- await checkPlaylistElementType(group2, playlistServer1UUID2, VideoPlaylistElementType.REGULAR, position, name, 3)
- }
- })
- })
-
- describe('Managing playlist elements', function () {
-
- it('Should reorder the playlist', async function () {
- this.timeout(30000)
-
- {
- await commands[0].reorderElements({
- playlistId: playlistServer1Id,
- attributes: {
- startPosition: 2,
- insertAfterPosition: 3
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
- const names = body.data.map(v => v.video.name)
-
- expect(names).to.deep.equal([
- 'video 0 server 1',
- 'video 2 server 3',
- 'video 1 server 3',
- 'video 3 server 1',
- 'video 4 server 1',
- 'NSFW video',
- 'NSFW video',
- 'NSFW video'
- ])
- }
- }
-
- {
- await commands[0].reorderElements({
- playlistId: playlistServer1Id,
- attributes: {
- startPosition: 1,
- reorderLength: 3,
- insertAfterPosition: 4
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
- const names = body.data.map(v => v.video.name)
-
- expect(names).to.deep.equal([
- 'video 3 server 1',
- 'video 0 server 1',
- 'video 2 server 3',
- 'video 1 server 3',
- 'video 4 server 1',
- 'NSFW video',
- 'NSFW video',
- 'NSFW video'
- ])
- }
- }
-
- {
- await commands[0].reorderElements({
- playlistId: playlistServer1Id,
- attributes: {
- startPosition: 6,
- insertAfterPosition: 3
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data: elements } = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
- const names = elements.map(v => v.video.name)
-
- expect(names).to.deep.equal([
- 'video 3 server 1',
- 'video 0 server 1',
- 'video 2 server 3',
- 'NSFW video',
- 'video 1 server 3',
- 'video 4 server 1',
- 'NSFW video',
- 'NSFW video'
- ])
-
- for (let i = 1; i <= elements.length; i++) {
- expect(elements[i - 1].position).to.equal(i)
- }
- }
- }
- })
-
- it('Should update startTimestamp/endTimestamp of some elements', async function () {
- this.timeout(30000)
-
- await commands[0].updateElement({
- playlistId: playlistServer1Id,
- elementId: playlistElementServer1Video4,
- attributes: {
- startTimestamp: 1
- }
- })
-
- await commands[0].updateElement({
- playlistId: playlistServer1Id,
- elementId: playlistElementServer1Video5,
- attributes: {
- stopTimestamp: null
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data: elements } = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
-
- expect(elements[0].video.name).to.equal('video 3 server 1')
- expect(elements[0].position).to.equal(1)
- expect(elements[0].startTimestamp).to.equal(1)
- expect(elements[0].stopTimestamp).to.equal(35)
-
- expect(elements[5].video.name).to.equal('video 4 server 1')
- expect(elements[5].position).to.equal(6)
- expect(elements[5].startTimestamp).to.equal(45)
- expect(elements[5].stopTimestamp).to.be.null
- }
- })
-
- it('Should check videos existence in my playlist', async function () {
- const videoIds = [
- servers[0].store.videos[0].id,
- 42000,
- servers[0].store.videos[3].id,
- 43000,
- servers[0].store.videos[4].id
- ]
- const obj = await commands[0].videosExist({ videoIds })
-
- {
- const elem = obj[servers[0].store.videos[0].id]
- expect(elem).to.have.lengthOf(1)
- expect(elem[0].playlistElementId).to.exist
- expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
- expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
- expect(elem[0].playlistId).to.equal(playlistServer1Id)
- expect(elem[0].startTimestamp).to.equal(15)
- expect(elem[0].stopTimestamp).to.equal(28)
- }
-
- {
- const elem = obj[servers[0].store.videos[3].id]
- expect(elem).to.have.lengthOf(1)
- expect(elem[0].playlistElementId).to.equal(playlistElementServer1Video4)
- expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
- expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
- expect(elem[0].playlistId).to.equal(playlistServer1Id)
- expect(elem[0].startTimestamp).to.equal(1)
- expect(elem[0].stopTimestamp).to.equal(35)
- }
-
- {
- const elem = obj[servers[0].store.videos[4].id]
- expect(elem).to.have.lengthOf(1)
- expect(elem[0].playlistId).to.equal(playlistServer1Id)
- expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
- expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
- expect(elem[0].startTimestamp).to.equal(45)
- expect(elem[0].stopTimestamp).to.equal(null)
- }
-
- expect(obj[42000]).to.have.lengthOf(0)
- expect(obj[43000]).to.have.lengthOf(0)
- })
-
- it('Should automatically update updatedAt field of playlists', async function () {
- const server = servers[1]
- const videoId = servers[1].store.videos[5].id
-
- async function getPlaylistNames () {
- const { data } = await server.playlists.listByAccount({ token: server.accessToken, handle: 'root', sort: '-updatedAt' })
-
- return data.map(p => p.displayName)
- }
-
- const attributes = { videoId }
- const element1 = await server.playlists.addElement({ playlistId: playlistServer2Id1, attributes })
- const element2 = await server.playlists.addElement({ playlistId: playlistServer2Id2, attributes })
-
- const names1 = await getPlaylistNames()
- expect(names1[0]).to.equal('playlist 3 updated')
- expect(names1[1]).to.equal('playlist 2')
-
- await server.playlists.removeElement({ playlistId: playlistServer2Id1, elementId: element1.id })
-
- const names2 = await getPlaylistNames()
- expect(names2[0]).to.equal('playlist 2')
- expect(names2[1]).to.equal('playlist 3 updated')
-
- await server.playlists.removeElement({ playlistId: playlistServer2Id2, elementId: element2.id })
-
- const names3 = await getPlaylistNames()
- expect(names3[0]).to.equal('playlist 3 updated')
- expect(names3[1]).to.equal('playlist 2')
- })
-
- it('Should delete some elements', async function () {
- this.timeout(30000)
-
- await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementServer1Video4 })
- await commands[0].removeElement({ playlistId: playlistServer1Id, elementId: playlistElementNSFW })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const body = await server.playlists.listVideos({ playlistId: playlistServer1UUID, start: 0, count: 10 })
- expect(body.total).to.equal(6)
-
- const elements = body.data
- expect(elements).to.have.lengthOf(6)
-
- expect(elements[0].video.name).to.equal('video 0 server 1')
- expect(elements[0].position).to.equal(1)
-
- expect(elements[1].video.name).to.equal('video 2 server 3')
- expect(elements[1].position).to.equal(2)
-
- expect(elements[2].video.name).to.equal('video 1 server 3')
- expect(elements[2].position).to.equal(3)
-
- expect(elements[3].video.name).to.equal('video 4 server 1')
- expect(elements[3].position).to.equal(4)
-
- expect(elements[4].video.name).to.equal('NSFW video')
- expect(elements[4].position).to.equal(5)
-
- expect(elements[5].video.name).to.equal('NSFW video')
- expect(elements[5].position).to.equal(6)
- }
- })
-
- it('Should be able to create a public playlist, and set it to private', async function () {
- this.timeout(30000)
-
- const videoPlaylistIds = await commands[0].create({
- attributes: {
- displayName: 'my super public playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].store.channel.id
- }
- })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.playlists.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const attributes = { privacy: VideoPlaylistPrivacy.PRIVATE }
- await commands[0].update({ playlistId: videoPlaylistIds.id, attributes })
-
- await waitJobs(servers)
-
- for (const server of [ servers[1], servers[2] ]) {
- await server.playlists.get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
-
- await commands[0].get({ playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await commands[0].get({ token: servers[0].accessToken, playlistId: videoPlaylistIds.uuid, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- describe('Playlist deletion', function () {
-
- it('Should delete the playlist on server 1 and delete on server 2 and 3', async function () {
- this.timeout(30000)
-
- await commands[0].delete({ playlistId: playlistServer1Id })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.playlists.get({ playlistId: playlistServer1UUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
- })
-
- it('Should have deleted the thumbnail on server 1, 2 and 3', async function () {
- this.timeout(30000)
-
- for (const server of servers) {
- await checkPlaylistFilesWereRemoved(playlistServer1UUID, server)
- }
- })
-
- it('Should unfollow servers 1 and 2 and hide their playlists', async function () {
- this.timeout(30000)
-
- const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'my super playlist')
-
- {
- const body = await servers[2].playlists.list({ start: 0, count: 5 })
- expect(body.total).to.equal(3)
-
- expect(finder(body.data)).to.not.be.undefined
- }
-
- await servers[2].follows.unfollow({ target: servers[0] })
-
- {
- const body = await servers[2].playlists.list({ start: 0, count: 5 })
- expect(body.total).to.equal(1)
-
- expect(finder(body.data)).to.be.undefined
- }
- })
-
- it('Should delete a channel and put the associated playlist in private mode', async function () {
- this.timeout(30000)
-
- const channel = await servers[0].channels.create({ attributes: { name: 'super_channel', displayName: 'super channel' } })
-
- const playlistCreated = await commands[0].create({
- attributes: {
- displayName: 'channel playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: channel.id
- }
- })
-
- await waitJobs(servers)
-
- await servers[0].channels.delete({ channelName: 'super_channel' })
-
- await waitJobs(servers)
-
- const body = await commands[0].get({ token: servers[0].accessToken, playlistId: playlistCreated.uuid })
- expect(body.displayName).to.equal('channel playlist')
- expect(body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
-
- await servers[1].playlists.get({ playlistId: playlistCreated.uuid, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
-
- it('Should delete an account and delete its playlists', async function () {
- this.timeout(30000)
-
- const { userId, token } = await servers[0].users.generate('user_1')
-
- const { videoChannels } = await servers[0].users.getMyInfo({ token })
- const userChannel = videoChannels[0]
-
- await commands[0].create({
- attributes: {
- displayName: 'playlist to be deleted',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: userChannel.id
- }
- })
-
- await waitJobs(servers)
-
- const finder = (data: VideoPlaylist[]) => data.find(p => p.displayName === 'playlist to be deleted')
-
- {
- for (const server of [ servers[0], servers[1] ]) {
- const body = await server.playlists.list({ start: 0, count: 15 })
-
- expect(finder(body.data)).to.not.be.undefined
- }
- }
-
- await servers[0].users.remove({ userId })
- await waitJobs(servers)
-
- {
- for (const server of [ servers[0], servers[1] ]) {
- const body = await server.playlists.list({ start: 0, count: 15 })
-
- expect(finder(body.data)).to.be.undefined
- }
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-privacy.ts b/server/tests/api/videos/video-privacy.ts
deleted file mode 100644
index de96bcfcc..000000000
--- a/server/tests/api/videos/video-privacy.ts
+++ /dev/null
@@ -1,287 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/server-commands'
-
-describe('Test video privacy', function () {
- const servers: PeerTubeServer[] = []
- let anotherUserToken: string
-
- let privateVideoId: number
- let privateVideoUUID: string
-
- let internalVideoId: number
- let internalVideoUUID: string
-
- let unlistedVideo: VideoCreateResult
- let nonFederatedUnlistedVideoUUID: string
-
- let now: number
-
- const dontFederateUnlistedConfig = {
- federation: {
- videos: {
- federate_unlisted: false
- }
- }
- }
-
- before(async function () {
- this.timeout(50000)
-
- // Run servers
- servers.push(await createSingleServer(1, dontFederateUnlistedConfig))
- servers.push(await createSingleServer(2))
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Private and internal videos', function () {
-
- it('Should upload a private and internal videos on server 1', async function () {
- this.timeout(50000)
-
- for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) {
- const attributes = { privacy }
- await servers[0].videos.upload({ attributes })
- }
-
- await waitJobs(servers)
- })
-
- it('Should not have these private and internal videos on server 2', async function () {
- const { total, data } = await servers[1].videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- })
-
- it('Should not list the private and internal videos for an unauthenticated user on server 1', async function () {
- const { total, data } = await servers[0].videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- })
-
- it('Should not list the private video and list the internal video for an authenticated user on server 1', async function () {
- const { total, data } = await servers[0].videos.listWithToken()
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- expect(data[0].privacy.id).to.equal(VideoPrivacy.INTERNAL)
- })
-
- it('Should list my (private and internal) videos', async function () {
- const { total, data } = await servers[0].videos.listMyVideos()
-
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- const privateVideo = data.find(v => v.privacy.id === VideoPrivacy.PRIVATE)
- privateVideoId = privateVideo.id
- privateVideoUUID = privateVideo.uuid
-
- const internalVideo = data.find(v => v.privacy.id === VideoPrivacy.INTERNAL)
- internalVideoId = internalVideo.id
- internalVideoUUID = internalVideo.uuid
- })
-
- it('Should not be able to watch the private/internal video with non authenticated user', async function () {
- await servers[0].videos.get({ id: privateVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- await servers[0].videos.get({ id: internalVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should not be able to watch the private video with another user', async function () {
- const user = {
- username: 'hello',
- password: 'super password'
- }
- await servers[0].users.create({ username: user.username, password: user.password })
-
- anotherUserToken = await servers[0].login.getAccessToken(user)
-
- await servers[0].videos.getWithToken({
- token: anotherUserToken,
- id: privateVideoUUID,
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should be able to watch the internal video with another user', async function () {
- await servers[0].videos.getWithToken({ token: anotherUserToken, id: internalVideoUUID })
- })
-
- it('Should be able to watch the private video with the correct user', async function () {
- await servers[0].videos.getWithToken({ id: privateVideoUUID })
- })
- })
-
- describe('Unlisted videos', function () {
-
- it('Should upload an unlisted video on server 2', async function () {
- this.timeout(120000)
-
- const attributes = {
- name: 'unlisted video',
- privacy: VideoPrivacy.UNLISTED
- }
- await servers[1].videos.upload({ attributes })
-
- // Server 2 has transcoding enabled
- await waitJobs(servers)
- })
-
- it('Should not have this unlisted video listed on server 1 and 2', async function () {
- for (const server of servers) {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
- })
-
- it('Should list my (unlisted) videos', async function () {
- const { total, data } = await servers[1].videos.listMyVideos()
-
- expect(total).to.equal(1)
- expect(data).to.have.lengthOf(1)
-
- unlistedVideo = data[0]
- })
-
- it('Should not be able to get this unlisted video using its id', async function () {
- await servers[1].videos.get({ id: unlistedVideo.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should be able to get this unlisted video using its uuid/shortUUID', async function () {
- for (const server of servers) {
- for (const id of [ unlistedVideo.uuid, unlistedVideo.shortUUID ]) {
- const video = await server.videos.get({ id })
-
- expect(video.name).to.equal('unlisted video')
- }
- }
- })
-
- it('Should upload a non-federating unlisted video to server 1', async function () {
- this.timeout(30000)
-
- const attributes = {
- name: 'unlisted video',
- privacy: VideoPrivacy.UNLISTED
- }
- await servers[0].videos.upload({ attributes })
-
- await waitJobs(servers)
- })
-
- it('Should list my new unlisted video', async function () {
- const { total, data } = await servers[0].videos.listMyVideos()
-
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
-
- nonFederatedUnlistedVideoUUID = data[0].uuid
- })
-
- it('Should be able to get non-federated unlisted video from origin', async function () {
- const video = await servers[0].videos.get({ id: nonFederatedUnlistedVideoUUID })
-
- expect(video.name).to.equal('unlisted video')
- })
-
- it('Should not be able to get non-federated unlisted video from federated server', async function () {
- await servers[1].videos.get({ id: nonFederatedUnlistedVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- })
- })
-
- describe('Privacy update', function () {
-
- it('Should update the private and internal videos to public on server 1', async function () {
- this.timeout(100000)
-
- now = Date.now()
-
- {
- const attributes = {
- name: 'private video becomes public',
- privacy: VideoPrivacy.PUBLIC
- }
-
- await servers[0].videos.update({ id: privateVideoId, attributes })
- }
-
- {
- const attributes = {
- name: 'internal video becomes public',
- privacy: VideoPrivacy.PUBLIC
- }
- await servers[0].videos.update({ id: internalVideoId, attributes })
- }
-
- await wait(10000)
- await waitJobs(servers)
- })
-
- it('Should have this new public video listed on server 1 and 2', async function () {
- for (const server of servers) {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
- expect(data).to.have.lengthOf(2)
-
- const privateVideo = data.find(v => v.name === 'private video becomes public')
- const internalVideo = data.find(v => v.name === 'internal video becomes public')
-
- expect(privateVideo).to.not.be.undefined
- expect(internalVideo).to.not.be.undefined
-
- expect(new Date(privateVideo.publishedAt).getTime()).to.be.at.least(now)
- // We don't change the publish date of internal videos
- expect(new Date(internalVideo.publishedAt).getTime()).to.be.below(now)
-
- expect(privateVideo.privacy.id).to.equal(VideoPrivacy.PUBLIC)
- expect(internalVideo.privacy.id).to.equal(VideoPrivacy.PUBLIC)
- }
- })
-
- it('Should set these videos as private and internal', async function () {
- await servers[0].videos.update({ id: internalVideoId, attributes: { privacy: VideoPrivacy.PRIVATE } })
- await servers[0].videos.update({ id: privateVideoId, attributes: { privacy: VideoPrivacy.INTERNAL } })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(0)
- expect(data).to.have.lengthOf(0)
- }
-
- {
- const { total, data } = await servers[0].videos.listMyVideos()
- expect(total).to.equal(3)
- expect(data).to.have.lengthOf(3)
-
- const privateVideo = data.find(v => v.name === 'private video becomes public')
- const internalVideo = data.find(v => v.name === 'internal video becomes public')
-
- expect(privateVideo).to.not.be.undefined
- expect(internalVideo).to.not.be.undefined
-
- expect(privateVideo.privacy.id).to.equal(VideoPrivacy.INTERNAL)
- expect(internalVideo.privacy.id).to.equal(VideoPrivacy.PRIVATE)
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-schedule-update.ts b/server/tests/api/videos/video-schedule-update.ts
deleted file mode 100644
index bf341c648..000000000
--- a/server/tests/api/videos/video-schedule-update.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-function in10Seconds () {
- const now = new Date()
- now.setSeconds(now.getSeconds() + 10)
-
- return now
-}
-
-describe('Test video update scheduler', function () {
- let servers: PeerTubeServer[] = []
- let video2UUID: string
-
- before(async function () {
- this.timeout(30000)
-
- // Run servers
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should upload a video and schedule an update in 10 seconds', async function () {
- const attributes = {
- name: 'video 1',
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: in10Seconds().toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
-
- await servers[0].videos.upload({ attributes })
-
- await waitJobs(servers)
- })
-
- it('Should not list the video (in privacy mode)', async function () {
- for (const server of servers) {
- const { total } = await server.videos.list()
-
- expect(total).to.equal(0)
- }
- })
-
- it('Should have my scheduled video in my account videos', async function () {
- const { total, data } = await servers[0].videos.listMyVideos()
- expect(total).to.equal(1)
-
- const videoFromList = data[0]
- const videoFromGet = await servers[0].videos.getWithToken({ id: videoFromList.uuid })
-
- for (const video of [ videoFromList, videoFromGet ]) {
- expect(video.name).to.equal('video 1')
- expect(video.privacy.id).to.equal(VideoPrivacy.PRIVATE)
- expect(new Date(video.scheduledUpdate.updateAt)).to.be.above(new Date())
- expect(video.scheduledUpdate.privacy).to.equal(VideoPrivacy.PUBLIC)
- }
- })
-
- it('Should wait some seconds and have the video in public privacy', async function () {
- this.timeout(50000)
-
- await wait(15000)
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
-
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('video 1')
- }
- })
-
- it('Should upload a video without scheduling an update', async function () {
- const attributes = {
- name: 'video 2',
- privacy: VideoPrivacy.PRIVATE
- }
-
- const { uuid } = await servers[0].videos.upload({ attributes })
- video2UUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should update a video by scheduling an update', async function () {
- const attributes = {
- name: 'video 2 updated',
- scheduleUpdate: {
- updateAt: in10Seconds().toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
-
- await servers[0].videos.update({ id: video2UUID, attributes })
- await waitJobs(servers)
- })
-
- it('Should not display the updated video', async function () {
- for (const server of servers) {
- const { total } = await server.videos.list()
-
- expect(total).to.equal(1)
- }
- })
-
- it('Should have my scheduled updated video in my account videos', async function () {
- const { total, data } = await servers[0].videos.listMyVideos()
- expect(total).to.equal(2)
-
- const video = data.find(v => v.uuid === video2UUID)
- expect(video).not.to.be.undefined
-
- expect(video.name).to.equal('video 2 updated')
- expect(video.privacy.id).to.equal(VideoPrivacy.PRIVATE)
-
- expect(new Date(video.scheduledUpdate.updateAt)).to.be.above(new Date())
- expect(video.scheduledUpdate.privacy).to.equal(VideoPrivacy.PUBLIC)
- })
-
- it('Should wait some seconds and have the updated video in public privacy', async function () {
- this.timeout(20000)
-
- await wait(15000)
- await waitJobs(servers)
-
- for (const server of servers) {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
-
- const video = data.find(v => v.uuid === video2UUID)
- expect(video).not.to.be.undefined
- expect(video.name).to.equal('video 2 updated')
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-source.ts b/server/tests/api/videos/video-source.ts
deleted file mode 100644
index 1f394f904..000000000
--- a/server/tests/api/videos/video-source.ts
+++ /dev/null
@@ -1,447 +0,0 @@
-import { expect } from 'chai'
-import { expectStartWith } from '@server/tests/shared'
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { areMockObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test a video file replacement', function () {
- let servers: PeerTubeServer[] = []
-
- let replaceDate: Date
- let userToken: string
- let uuid: string
-
- before(async function () {
- this.timeout(50000)
-
- servers = await createMultipleServers(2)
-
- // Get the access tokens
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- await servers[0].config.enableFileUpdate()
-
- userToken = await servers[0].users.generateUserAndToken('user1')
-
- // Server 1 and server 2 follow each other
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Getting latest video source', () => {
- const fixture = 'video_short.webm'
- const uuids: string[] = []
-
- it('Should get the source filename with legacy upload', async function () {
- this.timeout(30000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video', fixture }, mode: 'legacy' })
- uuids.push(uuid)
-
- const source = await servers[0].videos.getSource({ id: uuid })
- expect(source.filename).to.equal(fixture)
- })
-
- it('Should get the source filename with resumable upload', async function () {
- this.timeout(30000)
-
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'my video', fixture }, mode: 'resumable' })
- uuids.push(uuid)
-
- const source = await servers[0].videos.getSource({ id: uuid })
- expect(source.filename).to.equal(fixture)
- })
-
- after(async function () {
- this.timeout(60000)
-
- for (const uuid of uuids) {
- await servers[0].videos.remove({ id: uuid })
- }
-
- await waitJobs(servers)
- })
- })
-
- describe('Updating video source', function () {
-
- describe('Filesystem', function () {
-
- it('Should replace a video file with transcoding disabled', async function () {
- this.timeout(120000)
-
- await servers[0].config.disableTranscoding()
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'fs without transcoding', fixture: 'video_short_720p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(1)
- expect(files[0].resolution.id).to.equal(720)
- }
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(1)
- expect(files[0].resolution.id).to.equal(360)
- }
- })
-
- it('Should replace a video file with transcoding enabled', async function () {
- this.timeout(120000)
-
- const previousPaths: string[] = []
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
-
- const { uuid: videoUUID } = await servers[0].videos.quickUpload({ name: 'fs with transcoding', fixture: 'video_short_720p.mp4' })
- uuid = videoUUID
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
- expect(video.inputFileUpdatedAt).to.be.null
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(6 * 2)
-
- // Grab old paths to ensure we'll regenerate
-
- previousPaths.push(video.previewPath)
- previousPaths.push(video.thumbnailPath)
-
- for (const file of files) {
- previousPaths.push(file.fileUrl)
- previousPaths.push(file.torrentUrl)
- previousPaths.push(file.metadataUrl)
-
- const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
- previousPaths.push(JSON.stringify(metadata))
- }
-
- const { storyboards } = await server.storyboard.list({ id: uuid })
- for (const s of storyboards) {
- previousPaths.push(s.storyboardPath)
- }
- }
-
- replaceDate = new Date()
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- expect(video.inputFileUpdatedAt).to.not.be.null
- expect(new Date(video.inputFileUpdatedAt)).to.be.above(replaceDate)
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(4 * 2)
-
- expect(previousPaths).to.not.include(video.previewPath)
- expect(previousPaths).to.not.include(video.thumbnailPath)
-
- await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
-
- for (const file of files) {
- expect(previousPaths).to.not.include(file.fileUrl)
- expect(previousPaths).to.not.include(file.torrentUrl)
- expect(previousPaths).to.not.include(file.metadataUrl)
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 })
-
- const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
- expect(previousPaths).to.not.include(JSON.stringify(metadata))
- }
-
- const { storyboards } = await server.storyboard.list({ id: uuid })
- for (const s of storyboards) {
- expect(previousPaths).to.not.include(s.storyboardPath)
-
- await makeGetRequest({ url: server.url, path: s.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- await servers[0].config.enableMinimumTranscoding()
- })
-
- it('Should have cleaned up old files', async function () {
- {
- const count = await servers[0].servers.countFiles('storyboards')
- expect(count).to.equal(2)
- }
-
- {
- const count = await servers[0].servers.countFiles('web-videos')
- expect(count).to.equal(5 + 1) // +1 for private directory
- }
-
- {
- const count = await servers[0].servers.countFiles('streaming-playlists/hls')
- expect(count).to.equal(1 + 1) // +1 for private directory
- }
-
- {
- const count = await servers[0].servers.countFiles('torrents')
- expect(count).to.equal(9)
- }
- })
-
- it('Should have the correct source input', async function () {
- const source = await servers[0].videos.getSource({ id: uuid })
-
- expect(source.filename).to.equal('video_short_360p.mp4')
- expect(new Date(source.createdAt)).to.be.above(replaceDate)
- })
-
- it('Should not have regenerated miniatures that were previously uploaded', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.upload({
- attributes: {
- name: 'custom miniatures',
- thumbnailfile: 'custom-thumbnail.jpg',
- previewfile: 'custom-preview.jpg'
- }
- })
-
- await waitJobs(servers)
-
- const previousPaths: string[] = []
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- previousPaths.push(video.previewPath)
- previousPaths.push(video.thumbnailPath)
-
- await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- expect(previousPaths).to.include(video.previewPath)
- expect(previousPaths).to.include(video.thumbnailPath)
-
- await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
- await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
- })
-
- describe('Autoblacklist', function () {
-
- function updateAutoBlacklist (enabled: boolean) {
- return servers[0].config.updateExistingSubConfig({
- newConfig: {
- autoBlacklist: {
- videos: {
- ofUsers: {
- enabled
- }
- }
- }
- }
- })
- }
-
- async function expectBlacklist (uuid: string, value: boolean) {
- const video = await servers[0].videos.getWithToken({ id: uuid })
-
- expect(video.blacklisted).to.equal(value)
- }
-
- before(async function () {
- await updateAutoBlacklist(true)
- })
-
- it('Should auto blacklist an unblacklisted video after file replacement', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
- await waitJobs(servers)
- await expectBlacklist(uuid, true)
-
- await servers[0].blacklist.remove({ videoId: uuid })
- await expectBlacklist(uuid, false)
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- await expectBlacklist(uuid, true)
- })
-
- it('Should auto blacklist an already blacklisted video after file replacement', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
- await waitJobs(servers)
- await expectBlacklist(uuid, true)
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- await expectBlacklist(uuid, true)
- })
-
- it('Should not auto blacklist if auto blacklist has been disabled between the upload and the replacement', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ token: userToken, name: 'user video' })
- await waitJobs(servers)
- await expectBlacklist(uuid, true)
-
- await servers[0].blacklist.remove({ videoId: uuid })
- await expectBlacklist(uuid, false)
-
- await updateAutoBlacklist(false)
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, token: userToken, fixture: 'video_short1.webm' })
- await waitJobs(servers)
-
- await expectBlacklist(uuid, false)
- })
- })
-
- describe('With object storage enabled', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(120000)
-
- const configOverride = objectStorage.getDefaultMockConfig()
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
- await servers[0].run(configOverride)
- })
-
- it('Should replace a video file with transcoding disabled', async function () {
- this.timeout(120000)
-
- await servers[0].config.disableTranscoding()
-
- const { uuid } = await servers[0].videos.quickUpload({
- name: 'object storage without transcoding',
- fixture: 'video_short_720p.mp4'
- })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(1)
- expect(files[0].resolution.id).to.equal(720)
- expectStartWith(files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_360p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(1)
- expect(files[0].resolution.id).to.equal(360)
- expectStartWith(files[0].fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
- })
-
- it('Should replace a video file with transcoding enabled', async function () {
- this.timeout(120000)
-
- const previousPaths: string[] = []
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
-
- const { uuid: videoUUID } = await servers[0].videos.quickUpload({
- name: 'object storage with transcoding',
- fixture: 'video_short_360p.mp4'
- })
- uuid = videoUUID
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(4 * 2)
-
- for (const file of files) {
- previousPaths.push(file.fileUrl)
- }
-
- for (const file of video.files) {
- expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
-
- for (const file of video.streamingPlaylists[0].files) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- }
- }
-
- await servers[0].videos.replaceSourceFile({ videoId: uuid, fixture: 'video_short_240p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
-
- const files = getAllFiles(video)
- expect(files).to.have.lengthOf(3 * 2)
-
- for (const file of files) {
- expect(previousPaths).to.not.include(file.fileUrl)
- }
-
- for (const file of video.files) {
- expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
-
- for (const file of video.streamingPlaylists[0].files) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- }
- }
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/video-static-file-privacy.ts b/server/tests/api/videos/video-static-file-privacy.ts
deleted file mode 100644
index 0a9864134..000000000
--- a/server/tests/api/videos/video-static-file-privacy.ts
+++ /dev/null
@@ -1,600 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { decode } from 'magnet-uri'
-import { checkVideoFileTokenReinjection, expectStartWith, parseTorrentVideo } from '@server/tests/shared'
-import { getAllFiles, wait } from '@shared/core-utils'
-import { HttpStatusCode, LiveVideo, VideoDetails, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- findExternalSavedVideo,
- makeRawRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video static file privacy', function () {
- let server: PeerTubeServer
- let userToken: string
-
- before(async function () {
- this.timeout(50000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- userToken = await server.users.generateUserAndToken('user1')
- })
-
- describe('VOD static file path', function () {
-
- function runSuite () {
-
- async function checkPrivateFiles (uuid: string) {
- const video = await server.videos.getWithToken({ id: uuid })
-
- for (const file of video.files) {
- expect(file.fileDownloadUrl).to.not.include('/private/')
- expectStartWith(file.fileUrl, server.url + '/static/web-videos/private/')
-
- const torrent = await parseTorrentVideo(server, file)
- expect(torrent.urlList).to.have.lengthOf(0)
-
- const magnet = decode(file.magnetUri)
- expect(magnet.urlList).to.have.lengthOf(0)
-
- await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const hls = video.streamingPlaylists[0]
- if (hls) {
- expectStartWith(hls.playlistUrl, server.url + '/static/streaming-playlists/hls/private/')
- expectStartWith(hls.segmentsSha256Url, server.url + '/static/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url: hls.playlistUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- async function checkPublicFiles (uuid: string) {
- const video = await server.videos.get({ id: uuid })
-
- for (const file of getAllFiles(video)) {
- expect(file.fileDownloadUrl).to.not.include('/private/')
- expect(file.fileUrl).to.not.include('/private/')
-
- const torrent = await parseTorrentVideo(server, file)
- expect(torrent.urlList[0]).to.not.include('private')
-
- const magnet = decode(file.magnetUri)
- expect(magnet.urlList[0]).to.not.include('private')
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: torrent.urlList[0], expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: magnet.urlList[0], expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const hls = video.streamingPlaylists[0]
- if (hls) {
- expect(hls.playlistUrl).to.not.include('private')
- expect(hls.segmentsSha256Url).to.not.include('private')
-
- await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- it('Should upload a private/internal/password protected video and have a private static path', async function () {
- this.timeout(120000)
-
- for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) {
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy })
- await waitJobs([ server ])
-
- await checkPrivateFiles(uuid)
- }
-
- const { uuid } = await server.videos.quickUpload({
- name: 'video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ 'my super password' ]
- })
- await waitJobs([ server ])
-
- await checkPrivateFiles(uuid)
- })
-
- it('Should upload a public video and update it as private/internal to have a private static path', async function () {
- this.timeout(120000)
-
- for (const privacy of [ VideoPrivacy.PRIVATE, VideoPrivacy.INTERNAL ]) {
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PUBLIC })
- await waitJobs([ server ])
-
- await server.videos.update({ id: uuid, attributes: { privacy } })
- await waitJobs([ server ])
-
- await checkPrivateFiles(uuid)
- }
- })
-
- it('Should upload a private video and update it to unlisted to have a public static path', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- await waitJobs([ server ])
-
- await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.UNLISTED } })
- await waitJobs([ server ])
-
- await checkPublicFiles(uuid)
- })
-
- it('Should upload an internal video and update it to public to have a public static path', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL })
- await waitJobs([ server ])
-
- await server.videos.update({ id: uuid, attributes: { privacy: VideoPrivacy.PUBLIC } })
- await waitJobs([ server ])
-
- await checkPublicFiles(uuid)
- })
-
- it('Should upload an internal video and schedule a public publish', async function () {
- this.timeout(120000)
-
- const attributes = {
- name: 'video',
- privacy: VideoPrivacy.PRIVATE,
- scheduleUpdate: {
- updateAt: new Date(Date.now() + 1000).toISOString(),
- privacy: VideoPrivacy.PUBLIC as VideoPrivacy.PUBLIC
- }
- }
-
- const { uuid } = await server.videos.upload({ attributes })
-
- await waitJobs([ server ])
- await wait(1000)
- await server.debug.sendCommand({ body: { command: 'process-update-videos-scheduler' } })
-
- await waitJobs([ server ])
-
- await checkPublicFiles(uuid)
- })
- }
-
- describe('Without transcoding', function () {
- runSuite()
- })
-
- describe('With transcoding', function () {
-
- before(async function () {
- await server.config.enableMinimumTranscoding()
- })
-
- runSuite()
- })
- })
-
- describe('VOD static file right check', function () {
- let unrelatedFileToken: string
-
- async function checkVideoFiles (options: {
- id: string
- expectedStatus: HttpStatusCode
- token: string
- videoFileToken: string
- videoPassword?: string
- }) {
- const { id, expectedStatus, token, videoFileToken, videoPassword } = options
-
- const video = await server.videos.getWithToken({ id })
-
- for (const file of getAllFiles(video)) {
- await makeRawRequest({ url: file.fileUrl, token, expectedStatus })
- await makeRawRequest({ url: file.fileDownloadUrl, token, expectedStatus })
-
- await makeRawRequest({ url: file.fileUrl, query: { videoFileToken }, expectedStatus })
- await makeRawRequest({ url: file.fileDownloadUrl, query: { videoFileToken }, expectedStatus })
-
- if (videoPassword) {
- const headers = { 'x-peertube-video-password': videoPassword }
- await makeRawRequest({ url: file.fileUrl, headers, expectedStatus })
- await makeRawRequest({ url: file.fileDownloadUrl, headers, expectedStatus })
- }
- }
-
- const hls = video.streamingPlaylists[0]
- await makeRawRequest({ url: hls.playlistUrl, token, expectedStatus })
- await makeRawRequest({ url: hls.segmentsSha256Url, token, expectedStatus })
-
- await makeRawRequest({ url: hls.playlistUrl, query: { videoFileToken }, expectedStatus })
- await makeRawRequest({ url: hls.segmentsSha256Url, query: { videoFileToken }, expectedStatus })
-
- if (videoPassword) {
- const headers = { 'x-peertube-video-password': videoPassword }
- await makeRawRequest({ url: hls.playlistUrl, token: null, headers, expectedStatus })
- await makeRawRequest({ url: hls.segmentsSha256Url, token: null, headers, expectedStatus })
- }
- }
-
- before(async function () {
- await server.config.enableMinimumTranscoding()
-
- const { uuid } = await server.videos.quickUpload({ name: 'another video' })
- unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
- })
-
- it('Should not be able to access a private video files without OAuth token and file token', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- await waitJobs([ server ])
-
- await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.FORBIDDEN_403, token: null, videoFileToken: null })
- })
-
- it('Should not be able to access password protected video files without OAuth token, file token and password', async function () {
- this.timeout(120000)
- const videoPassword = 'my super password'
-
- const { uuid } = await server.videos.quickUpload({
- name: 'password protected video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ videoPassword ]
- })
- await waitJobs([ server ])
-
- await checkVideoFiles({
- id: uuid,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- token: null,
- videoFileToken: null,
- videoPassword: null
- })
- })
-
- it('Should not be able to access an password video files with incorrect OAuth token, file token and password', async function () {
- this.timeout(120000)
- const videoPassword = 'my super password'
-
- const { uuid } = await server.videos.quickUpload({
- name: 'password protected video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ videoPassword ]
- })
- await waitJobs([ server ])
-
- await checkVideoFiles({
- id: uuid,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- token: userToken,
- videoFileToken: unrelatedFileToken,
- videoPassword: 'incorrectPassword'
- })
- })
-
- it('Should not be able to access an private video files without appropriate OAuth token and file token', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- await waitJobs([ server ])
-
- await checkVideoFiles({
- id: uuid,
- expectedStatus: HttpStatusCode.FORBIDDEN_403,
- token: userToken,
- videoFileToken: unrelatedFileToken
- })
- })
-
- it('Should be able to access a private video files with appropriate OAuth token or file token', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
-
- await waitJobs([ server ])
-
- await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken })
- })
-
- it('Should be able to access a password protected video files with appropriate OAuth token or file token', async function () {
- this.timeout(120000)
- const videoPassword = 'my super password'
-
- const { uuid } = await server.videos.quickUpload({
- name: 'video',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ videoPassword ]
- })
-
- const videoFileToken = await server.videoToken.getVideoFileToken({ token: null, videoId: uuid, videoPassword })
-
- await waitJobs([ server ])
-
- await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken, videoPassword })
- })
-
- it('Should reinject video file token', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.PRIVATE })
-
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
- await waitJobs([ server ])
-
- {
- const video = await server.videos.getWithToken({ id: uuid })
- const hls = video.streamingPlaylists[0]
- const query = { videoFileToken }
- const { text } = await makeRawRequest({ url: hls.playlistUrl, query, expectedStatus: HttpStatusCode.OK_200 })
-
- expect(text).to.not.include(videoFileToken)
- }
-
- {
- await checkVideoFileTokenReinjection({
- server,
- videoUUID: uuid,
- videoFileToken,
- resolutions: [ 240, 720 ],
- isLive: false
- })
- }
- })
-
- it('Should be able to access a private video of another user with an admin OAuth token or file token', async function () {
- this.timeout(120000)
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', token: userToken, privacy: VideoPrivacy.PRIVATE })
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
-
- await waitJobs([ server ])
-
- await checkVideoFiles({ id: uuid, expectedStatus: HttpStatusCode.OK_200, token: server.accessToken, videoFileToken })
- })
- })
-
- describe('Live static file path and check', function () {
- let normalLiveId: string
- let normalLive: LiveVideo
-
- let permanentLiveId: string
- let permanentLive: LiveVideo
-
- let passwordProtectedLiveId: string
- let passwordProtectedLive: LiveVideo
-
- const correctPassword = 'my super password'
-
- let unrelatedFileToken: string
-
- async function checkLiveFiles (options: { live: LiveVideo, liveId: string, videoPassword?: string }) {
- const { live, liveId, videoPassword } = options
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await server.live.waitUntilPublished({ videoId: liveId })
-
- const video = await server.videos.getWithToken({ id: liveId })
-
- const fileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid })
-
- const hls = video.streamingPlaylists[0]
-
- for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
- expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
-
- if (videoPassword) {
- await makeRawRequest({ url, headers: { 'x-peertube-video-password': videoPassword }, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({
- url,
- headers: { 'x-peertube-video-password': 'incorrectPassword' },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
-
- }
-
- await stopFfmpeg(ffmpegCommand)
- }
-
- async function checkReplay (replay: VideoDetails) {
- const fileToken = await server.videoToken.getVideoFileToken({ videoId: replay.uuid })
-
- const hls = replay.streamingPlaylists[0]
- expect(hls.files).to.not.have.lengthOf(0)
-
- for (const file of hls.files) {
- await makeRawRequest({ url: file.fileUrl, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: file.fileUrl, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url: file.fileUrl, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({
- url: file.fileUrl,
- query: { videoFileToken: unrelatedFileToken },
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- }
-
- for (const url of [ hls.playlistUrl, hls.segmentsSha256Url ]) {
- expectStartWith(url, server.url + '/static/streaming-playlists/hls/private/')
-
- await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url, query: { videoFileToken: fileToken }, expectedStatus: HttpStatusCode.OK_200 })
-
- await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- await makeRawRequest({ url, query: { videoFileToken: unrelatedFileToken }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- }
- }
-
- before(async function () {
- await server.config.enableMinimumTranscoding()
-
- const { uuid } = await server.videos.quickUpload({ name: 'another video' })
- unrelatedFileToken = await server.videoToken.getVideoFileToken({ videoId: uuid })
-
- await server.config.enableLive({
- allowReplay: true,
- transcoding: true,
- resolutions: 'min'
- })
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: true,
- permanentLive: false,
- privacy: VideoPrivacy.PRIVATE
- })
- normalLiveId = video.uuid
- normalLive = live
- }
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: true,
- permanentLive: true,
- privacy: VideoPrivacy.PRIVATE
- })
- permanentLiveId = video.uuid
- permanentLive = live
- }
-
- {
- const { video, live } = await server.live.quickCreate({
- saveReplay: false,
- permanentLive: false,
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ correctPassword ]
- })
- passwordProtectedLiveId = video.uuid
- passwordProtectedLive = live
- }
- })
-
- it('Should create a private normal live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles({ live: normalLive, liveId: normalLiveId })
- })
-
- it('Should create a private permanent live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles({ live: permanentLive, liveId: permanentLiveId })
- })
-
- it('Should create a password protected live and have a private static path', async function () {
- this.timeout(240000)
-
- await checkLiveFiles({ live: passwordProtectedLive, liveId: passwordProtectedLiveId, videoPassword: correctPassword })
- })
-
- it('Should reinject video file token on permanent live', async function () {
- this.timeout(240000)
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: permanentLive.rtmpUrl, streamKey: permanentLive.streamKey })
- await server.live.waitUntilPublished({ videoId: permanentLiveId })
-
- const video = await server.videos.getWithToken({ id: permanentLiveId })
- const videoFileToken = await server.videoToken.getVideoFileToken({ videoId: video.uuid })
- const hls = video.streamingPlaylists[0]
-
- {
- const query = { videoFileToken }
- const { text } = await makeRawRequest({ url: hls.playlistUrl, query, expectedStatus: HttpStatusCode.OK_200 })
-
- expect(text).to.not.include(videoFileToken)
- }
-
- {
- await checkVideoFileTokenReinjection({
- server,
- videoUUID: permanentLiveId,
- videoFileToken,
- resolutions: [ 720 ],
- isLive: true
- })
- }
-
- await stopFfmpeg(ffmpegCommand)
- })
-
- it('Should have created a replay of the normal live with a private static path', async function () {
- this.timeout(240000)
-
- await server.live.waitUntilReplacedByReplay({ videoId: normalLiveId })
-
- const replay = await server.videos.getWithToken({ id: normalLiveId })
- await checkReplay(replay)
- })
-
- it('Should have created a replay of the permanent live with a private static path', async function () {
- this.timeout(240000)
-
- await server.live.waitUntilWaiting({ videoId: permanentLiveId })
- await waitJobs([ server ])
-
- const live = await server.videos.getWithToken({ id: permanentLiveId })
- const replayFromList = await findExternalSavedVideo(server, live)
- const replay = await server.videos.getWithToken({ id: replayFromList.id })
-
- await checkReplay(replay)
- })
- })
-
- describe('With static file right check disabled', function () {
- let videoUUID: string
-
- before(async function () {
- this.timeout(240000)
-
- await server.kill()
-
- await server.run({
- static_files: {
- private_files_require_auth: false
- }
- })
-
- const { uuid } = await server.videos.quickUpload({ name: 'video', privacy: VideoPrivacy.INTERNAL })
- videoUUID = uuid
-
- await waitJobs([ server ])
- })
-
- it('Should not check auth for private static files', async function () {
- const video = await server.videos.getWithToken({ id: videoUUID })
-
- for (const file of getAllFiles(video)) {
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const hls = video.streamingPlaylists[0]
- await makeRawRequest({ url: hls.playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: hls.segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/video-storyboard.ts b/server/tests/api/videos/video-storyboard.ts
deleted file mode 100644
index 07f371cad..000000000
--- a/server/tests/api/videos/video-storyboard.ts
+++ /dev/null
@@ -1,213 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readdir } from 'fs-extra'
-import { basename } from 'path'
-import { FIXTURE_URLS } from '@server/tests/shared'
-import { areHttpImportTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- sendRTMPStream,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-async function checkStoryboard (options: {
- server: PeerTubeServer
- uuid: string
- tilesCount?: number
- minSize?: number
-}) {
- const { server, uuid, tilesCount, minSize = 1000 } = options
-
- const { storyboards } = await server.storyboard.list({ id: uuid })
-
- expect(storyboards).to.have.lengthOf(1)
-
- const storyboard = storyboards[0]
-
- expect(storyboard.spriteDuration).to.equal(1)
- expect(storyboard.spriteHeight).to.equal(108)
- expect(storyboard.spriteWidth).to.equal(192)
- expect(storyboard.storyboardPath).to.exist
-
- if (tilesCount) {
- expect(storyboard.totalWidth).to.equal(192 * Math.min(tilesCount, 10))
- expect(storyboard.totalHeight).to.equal(108 * Math.max((tilesCount / 10), 1))
- }
-
- const { body } = await makeGetRequest({ url: server.url, path: storyboard.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(body.length).to.be.above(minSize)
-}
-
-describe('Test video storyboard', function () {
- let servers: PeerTubeServer[]
-
- let baseUUID: string
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should generate a storyboard after upload without transcoding', async function () {
- this.timeout(120000)
-
- // 5s video
- const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_short.webm' })
- baseUUID = uuid
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid, tilesCount: 5 })
- }
- })
-
- it('Should generate a storyboard after upload without transcoding with a long video', async function () {
- this.timeout(120000)
-
- // 124s video
- const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_very_long_10p.mp4' })
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid, tilesCount: 100 })
- }
- })
-
- it('Should generate a storyboard after upload with transcoding', async function () {
- this.timeout(120000)
-
- await servers[0].config.enableMinimumTranscoding()
-
- // 5s video
- const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_short.webm' })
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid, tilesCount: 5 })
- }
- })
-
- it('Should generate a storyboard after an audio upload', async function () {
- this.timeout(120000)
-
- // 6s audio
- const attributes = { name: 'audio', fixture: 'sample.ogg' }
- const { uuid } = await servers[0].videos.upload({ attributes, mode: 'legacy' })
- await waitJobs(servers)
-
- for (const server of servers) {
- try {
- await checkStoryboard({ server, uuid, tilesCount: 6, minSize: 250 })
- } catch { // FIXME: to remove after ffmpeg CI upgrade, ffmpeg CI version (4.3) generates a 7.6s length video
- await checkStoryboard({ server, uuid, tilesCount: 8, minSize: 250 })
- }
- }
- })
-
- it('Should generate a storyboard after HTTP import', async function () {
- this.timeout(120000)
-
- if (areHttpImportTestsDisabled()) return
-
- // 3s video
- const { video } = await servers[0].imports.importVideo({
- attributes: {
- targetUrl: FIXTURE_URLS.goodVideo,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- })
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid: video.uuid, tilesCount: 3 })
- }
- })
-
- it('Should generate a storyboard after torrent import', async function () {
- this.timeout(120000)
-
- if (areHttpImportTestsDisabled()) return
-
- // 10s video
- const { video } = await servers[0].imports.importVideo({
- attributes: {
- magnetUri: FIXTURE_URLS.magnet,
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- })
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid: video.uuid, tilesCount: 10 })
- }
- })
-
- it('Should generate a storyboard after a live', async function () {
- this.timeout(240000)
-
- await servers[0].config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' })
-
- const { live, video } = await servers[0].live.quickCreate({
- saveReplay: true,
- permanentLive: false,
- privacy: VideoPrivacy.PUBLIC
- })
-
- const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
- await servers[0].live.waitUntilPublished({ videoId: video.id })
-
- await stopFfmpeg(ffmpegCommand)
-
- await servers[0].live.waitUntilReplacedByReplay({ videoId: video.id })
- await waitJobs(servers)
-
- for (const server of servers) {
- await checkStoryboard({ server, uuid: video.uuid })
- }
- })
-
- it('Should cleanup storyboards on video deletion', async function () {
- this.timeout(60000)
-
- const { storyboards } = await servers[0].storyboard.list({ id: baseUUID })
- const storyboardName = basename(storyboards[0].storyboardPath)
-
- const listFiles = () => {
- const storyboardPath = servers[0].getDirectoryPath('storyboards')
- return readdir(storyboardPath)
- }
-
- {
- const storyboads = await listFiles()
- expect(storyboads).to.include(storyboardName)
- }
-
- await servers[0].videos.remove({ id: baseUUID })
- await waitJobs(servers)
-
- {
- const storyboads = await listFiles()
- expect(storyboads).to.not.include(storyboardName)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/videos-common-filters.ts b/server/tests/api/videos/videos-common-filters.ts
deleted file mode 100644
index 48de7c537..000000000
--- a/server/tests/api/videos/videos-common-filters.ts
+++ /dev/null
@@ -1,489 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pick } from '@shared/core-utils'
-import { HttpStatusCode, UserRole, Video, VideoDetails, VideoInclude, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test videos filter', function () {
- let servers: PeerTubeServer[]
- let paths: string[]
- let remotePaths: string[]
-
- const subscriptionVideosPath = '/api/v1/users/me/subscriptions/videos'
-
- // ---------------------------------------------------------------
-
- before(async function () {
- this.timeout(240000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultAccountAvatar(servers)
-
- await servers[1].config.enableMinimumTranscoding()
-
- for (const server of servers) {
- const moderator = { username: 'moderator', password: 'my super password' }
- await server.users.create({ username: moderator.username, password: moderator.password, role: UserRole.MODERATOR })
- server['moderatorAccessToken'] = await server.login.getAccessToken(moderator)
-
- await server.videos.upload({ attributes: { name: 'public ' + server.serverNumber } })
-
- {
- const attributes = { name: 'unlisted ' + server.serverNumber, privacy: VideoPrivacy.UNLISTED }
- await server.videos.upload({ attributes })
- }
-
- {
- const attributes = { name: 'private ' + server.serverNumber, privacy: VideoPrivacy.PRIVATE }
- await server.videos.upload({ attributes })
- }
-
- // Subscribing to itself
- await server.subscriptions.add({ targetUri: 'root_channel@' + server.host })
- }
-
- await doubleFollow(servers[0], servers[1])
-
- paths = [
- `/api/v1/video-channels/root_channel/videos`,
- `/api/v1/accounts/root/videos`,
- '/api/v1/videos',
- '/api/v1/search/videos',
- subscriptionVideosPath
- ]
-
- remotePaths = [
- `/api/v1/video-channels/root_channel@${servers[1].host}/videos`,
- `/api/v1/accounts/root@${servers[1].host}/videos`,
- '/api/v1/videos',
- '/api/v1/search/videos'
- ]
- })
-
- describe('Check videos filters', function () {
-
- async function listVideos (options: {
- server: PeerTubeServer
- path: string
- isLocal?: boolean
- hasWebVideoFiles?: boolean
- hasHLSFiles?: boolean
- include?: VideoInclude
- privacyOneOf?: VideoPrivacy[]
- category?: number
- tagsAllOf?: string[]
- token?: string
- expectedStatus?: HttpStatusCode
- excludeAlreadyWatched?: boolean
- }) {
- const res = await makeGetRequest({
- url: options.server.url,
- path: options.path,
- token: options.token ?? options.server.accessToken,
- query: {
- ...pick(options, [
- 'isLocal',
- 'include',
- 'category',
- 'tagsAllOf',
- 'hasWebVideoFiles',
- 'hasHLSFiles',
- 'privacyOneOf',
- 'excludeAlreadyWatched'
- ]),
-
- sort: 'createdAt'
- },
- expectedStatus: options.expectedStatus ?? HttpStatusCode.OK_200
- })
-
- return res.body.data as Video[]
- }
-
- async function getVideosNames (
- options: {
- server: PeerTubeServer
- isLocal?: boolean
- include?: VideoInclude
- privacyOneOf?: VideoPrivacy[]
- token?: string
- expectedStatus?: HttpStatusCode
- skipSubscription?: boolean
- excludeAlreadyWatched?: boolean
- }
- ) {
- const { skipSubscription = false } = options
- const videosResults: string[][] = []
-
- for (const path of paths) {
- if (skipSubscription && path === subscriptionVideosPath) continue
-
- const videos = await listVideos({ ...options, path })
-
- videosResults.push(videos.map(v => v.name))
- }
-
- return videosResults
- }
-
- it('Should display local videos', async function () {
- for (const server of servers) {
- const namesResults = await getVideosNames({ server, isLocal: true })
-
- for (const names of namesResults) {
- expect(names).to.have.lengthOf(1)
- expect(names[0]).to.equal('public ' + server.serverNumber)
- }
- }
- })
-
- it('Should display local videos with hidden privacy by the admin or the moderator', async function () {
- for (const server of servers) {
- for (const token of [ server.accessToken, server['moderatorAccessToken'] ]) {
-
- const namesResults = await getVideosNames(
- {
- server,
- token,
- isLocal: true,
- privacyOneOf: [ VideoPrivacy.UNLISTED, VideoPrivacy.PUBLIC, VideoPrivacy.PRIVATE ],
- skipSubscription: true
- }
- )
-
- for (const names of namesResults) {
- expect(names).to.have.lengthOf(3)
-
- expect(names[0]).to.equal('public ' + server.serverNumber)
- expect(names[1]).to.equal('unlisted ' + server.serverNumber)
- expect(names[2]).to.equal('private ' + server.serverNumber)
- }
- }
- }
- })
-
- it('Should display all videos by the admin or the moderator', async function () {
- for (const server of servers) {
- for (const token of [ server.accessToken, server['moderatorAccessToken'] ]) {
-
- const [ channelVideos, accountVideos, videos, searchVideos ] = await getVideosNames({
- server,
- token,
- privacyOneOf: [ VideoPrivacy.UNLISTED, VideoPrivacy.PUBLIC, VideoPrivacy.PRIVATE ]
- })
-
- expect(channelVideos).to.have.lengthOf(3)
- expect(accountVideos).to.have.lengthOf(3)
-
- expect(videos).to.have.lengthOf(5)
- expect(searchVideos).to.have.lengthOf(5)
- }
- }
- })
-
- it('Should display only remote videos', async function () {
- this.timeout(120000)
-
- await servers[1].videos.upload({ attributes: { name: 'remote video' } })
-
- await waitJobs(servers)
-
- const finder = (videos: Video[]) => videos.find(v => v.name === 'remote video')
-
- for (const path of remotePaths) {
- {
- const videos = await listVideos({ server: servers[0], path })
- const video = finder(videos)
- expect(video).to.exist
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, isLocal: false })
- const video = finder(videos)
- expect(video).to.exist
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, isLocal: true })
- const video = finder(videos)
- expect(video).to.not.exist
- }
- }
- })
-
- it('Should include not published videos', async function () {
- await servers[0].config.enableLive({ allowReplay: false, transcoding: false })
- await servers[0].live.create({ fields: { name: 'live video', channelId: servers[0].store.channel.id, privacy: VideoPrivacy.PUBLIC } })
-
- const finder = (videos: Video[]) => videos.find(v => v.name === 'live video')
-
- for (const path of paths) {
- {
- const videos = await listVideos({ server: servers[0], path })
- const video = finder(videos)
- expect(video).to.not.exist
- expect(videos[0].state).to.not.exist
- expect(videos[0].waitTranscoding).to.not.exist
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, include: VideoInclude.NOT_PUBLISHED_STATE })
- const video = finder(videos)
- expect(video).to.exist
- expect(video.state).to.exist
- }
- }
- })
-
- it('Should include blacklisted videos', async function () {
- const { id } = await servers[0].videos.upload({ attributes: { name: 'blacklisted' } })
-
- await servers[0].blacklist.add({ videoId: id })
-
- const finder = (videos: Video[]) => videos.find(v => v.name === 'blacklisted')
-
- for (const path of paths) {
- {
- const videos = await listVideos({ server: servers[0], path })
- const video = finder(videos)
- expect(video).to.not.exist
- expect(videos[0].blacklisted).to.not.exist
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, include: VideoInclude.BLACKLISTED })
- const video = finder(videos)
- expect(video).to.exist
- expect(video.blacklisted).to.be.true
- }
- }
- })
-
- it('Should include videos from muted account', async function () {
- const finder = (videos: Video[]) => videos.find(v => v.name === 'remote video')
-
- await servers[0].blocklist.addToServerBlocklist({ account: 'root@' + servers[1].host })
-
- for (const path of remotePaths) {
- {
- const videos = await listVideos({ server: servers[0], path })
- const video = finder(videos)
- expect(video).to.not.exist
-
- // Some paths won't have videos
- if (videos[0]) {
- expect(videos[0].blockedOwner).to.not.exist
- expect(videos[0].blockedServer).to.not.exist
- }
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, include: VideoInclude.BLOCKED_OWNER })
-
- const video = finder(videos)
- expect(video).to.exist
- expect(video.blockedServer).to.be.false
- expect(video.blockedOwner).to.be.true
- }
- }
-
- await servers[0].blocklist.removeFromServerBlocklist({ account: 'root@' + servers[1].host })
- })
-
- it('Should include videos from muted server', async function () {
- const finder = (videos: Video[]) => videos.find(v => v.name === 'remote video')
-
- await servers[0].blocklist.addToServerBlocklist({ server: servers[1].host })
-
- for (const path of remotePaths) {
- {
- const videos = await listVideos({ server: servers[0], path })
- const video = finder(videos)
- expect(video).to.not.exist
-
- // Some paths won't have videos
- if (videos[0]) {
- expect(videos[0].blockedOwner).to.not.exist
- expect(videos[0].blockedServer).to.not.exist
- }
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, include: VideoInclude.BLOCKED_OWNER })
- const video = finder(videos)
- expect(video).to.exist
- expect(video.blockedServer).to.be.true
- expect(video.blockedOwner).to.be.false
- }
- }
-
- await servers[0].blocklist.removeFromServerBlocklist({ server: servers[1].host })
- })
-
- it('Should include video files', async function () {
- for (const path of paths) {
- {
- const videos = await listVideos({ server: servers[0], path })
-
- for (const video of videos) {
- const videoWithFiles = video as VideoDetails
-
- expect(videoWithFiles.files).to.not.exist
- expect(videoWithFiles.streamingPlaylists).to.not.exist
- }
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, include: VideoInclude.FILES })
-
- for (const video of videos) {
- const videoWithFiles = video as VideoDetails
-
- expect(videoWithFiles.files).to.exist
- expect(videoWithFiles.files).to.have.length.at.least(1)
- }
- }
- }
- })
-
- it('Should filter by tags and category', async function () {
- await servers[0].videos.upload({ attributes: { name: 'tag filter', tags: [ 'tag1', 'tag2' ] } })
- await servers[0].videos.upload({ attributes: { name: 'tag filter with category', tags: [ 'tag3' ], category: 4 } })
-
- for (const path of paths) {
- {
- const videos = await listVideos({ server: servers[0], path, tagsAllOf: [ 'tag1', 'tag2' ] })
- expect(videos).to.have.lengthOf(1)
- expect(videos[0].name).to.equal('tag filter')
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, tagsAllOf: [ 'tag1', 'tag3' ] })
- expect(videos).to.have.lengthOf(0)
- }
-
- {
- const { data, total } = await servers[0].videos.list({ tagsAllOf: [ 'tag3' ], categoryOneOf: [ 4 ] })
- expect(total).to.equal(1)
- expect(data[0].name).to.equal('tag filter with category')
- }
-
- {
- const { total } = await servers[0].videos.list({ tagsAllOf: [ 'tag4' ], categoryOneOf: [ 4 ] })
- expect(total).to.equal(0)
- }
- }
- })
-
- it('Should filter by HLS or Web Video files', async function () {
- this.timeout(360000)
-
- const finderFactory = (name: string) => (videos: Video[]) => videos.some(v => v.name === name)
-
- await servers[0].config.enableTranscoding({ hls: false, webVideo: true })
- await servers[0].videos.upload({ attributes: { name: 'web video' } })
- const hasWebVideo = finderFactory('web video')
-
- await waitJobs(servers)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: false })
- await servers[0].videos.upload({ attributes: { name: 'hls video' } })
- const hasHLS = finderFactory('hls video')
-
- await waitJobs(servers)
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
- await servers[0].videos.upload({ attributes: { name: 'hls and web video' } })
- const hasBoth = finderFactory('hls and web video')
-
- await waitJobs(servers)
-
- for (const path of paths) {
- {
- const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: true })
-
- expect(hasWebVideo(videos)).to.be.true
- expect(hasHLS(videos)).to.be.false
- expect(hasBoth(videos)).to.be.true
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: false })
-
- expect(hasWebVideo(videos)).to.be.false
- expect(hasHLS(videos)).to.be.true
- expect(hasBoth(videos)).to.be.false
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true })
-
- expect(hasWebVideo(videos)).to.be.false
- expect(hasHLS(videos)).to.be.true
- expect(hasBoth(videos)).to.be.true
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false })
-
- expect(hasWebVideo(videos)).to.be.true
- expect(hasHLS(videos)).to.be.false
- expect(hasBoth(videos)).to.be.false
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false, hasWebVideoFiles: false })
-
- expect(hasWebVideo(videos)).to.be.false
- expect(hasHLS(videos)).to.be.false
- expect(hasBoth(videos)).to.be.false
- }
-
- {
- const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true, hasWebVideoFiles: true })
-
- expect(hasWebVideo(videos)).to.be.false
- expect(hasHLS(videos)).to.be.false
- expect(hasBoth(videos)).to.be.true
- }
- }
- })
-
- it('Should filter already watched videos by the user', async function () {
- const { id } = await servers[0].videos.upload({ attributes: { name: 'video for history' } })
-
- for (const path of paths) {
- const videos = await listVideos({ server: servers[0], path, isLocal: true, excludeAlreadyWatched: true })
- const foundVideo = videos.find(video => video.id === id)
-
- expect(foundVideo).to.not.be.undefined
- }
- await servers[0].views.view({ id, currentTime: 1, token: servers[0].accessToken })
-
- for (const path of paths) {
- const videos = await listVideos({ server: servers[0], path, excludeAlreadyWatched: true })
- const foundVideo = videos.find(video => video.id === id)
-
- expect(foundVideo).to.be.undefined
- }
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts
deleted file mode 100644
index 6df26ab7d..000000000
--- a/server/tests/api/videos/videos-history.ts
+++ /dev/null
@@ -1,224 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { Video } from '@shared/models'
-import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test videos history', function () {
- let server: PeerTubeServer = null
- let video1Id: number
- let video1UUID: string
- let video2UUID: string
- let video3UUID: string
- let video3WatchedDate: Date
- let userAccessToken: string
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- // 10 seconds long
- const fixture = 'video_short1.webm'
-
- {
- const { id, uuid } = await server.videos.upload({ attributes: { name: 'video 1', fixture } })
- video1UUID = uuid
- video1Id = id
- }
-
- {
- const { uuid } = await server.videos.upload({ attributes: { name: 'video 2', fixture } })
- video2UUID = uuid
- }
-
- {
- const { uuid } = await server.videos.upload({ attributes: { name: 'video 3', fixture } })
- video3UUID = uuid
- }
-
- userAccessToken = await server.users.generateUserAndToken('user_1')
- })
-
- it('Should get videos, without watching history', async function () {
- const { data } = await server.videos.listWithToken()
-
- for (const video of data) {
- const videoDetails = await server.videos.getWithToken({ id: video.id })
-
- expect(video.userHistory).to.be.undefined
- expect(videoDetails.userHistory).to.be.undefined
- }
- })
-
- it('Should watch the first and second video', async function () {
- await server.views.view({ id: video2UUID, token: server.accessToken, currentTime: 8 })
- await server.views.view({ id: video1UUID, token: server.accessToken, currentTime: 3 })
- })
-
- it('Should return the correct history when listing, searching and getting videos', async function () {
- const videosOfVideos: Video[][] = []
-
- {
- const { data } = await server.videos.listWithToken()
- videosOfVideos.push(data)
- }
-
- {
- const body = await server.search.searchVideos({ token: server.accessToken, search: 'video' })
- videosOfVideos.push(body.data)
- }
-
- for (const videos of videosOfVideos) {
- const video1 = videos.find(v => v.uuid === video1UUID)
- const video2 = videos.find(v => v.uuid === video2UUID)
- const video3 = videos.find(v => v.uuid === video3UUID)
-
- expect(video1.userHistory).to.not.be.undefined
- expect(video1.userHistory.currentTime).to.equal(3)
-
- expect(video2.userHistory).to.not.be.undefined
- expect(video2.userHistory.currentTime).to.equal(8)
-
- expect(video3.userHistory).to.be.undefined
- }
-
- {
- const videoDetails = await server.videos.getWithToken({ id: video1UUID })
-
- expect(videoDetails.userHistory).to.not.be.undefined
- expect(videoDetails.userHistory.currentTime).to.equal(3)
- }
-
- {
- const videoDetails = await server.videos.getWithToken({ id: video2UUID })
-
- expect(videoDetails.userHistory).to.not.be.undefined
- expect(videoDetails.userHistory.currentTime).to.equal(8)
- }
-
- {
- const videoDetails = await server.videos.getWithToken({ id: video3UUID })
-
- expect(videoDetails.userHistory).to.be.undefined
- }
- })
-
- it('Should have these videos when listing my history', async function () {
- video3WatchedDate = new Date()
- await server.views.view({ id: video3UUID, token: server.accessToken, currentTime: 2 })
-
- const body = await server.history.list()
-
- expect(body.total).to.equal(3)
-
- const videos = body.data
- expect(videos[0].name).to.equal('video 3')
- expect(videos[1].name).to.equal('video 1')
- expect(videos[2].name).to.equal('video 2')
- })
-
- it('Should not have videos history on another user', async function () {
- const body = await server.history.list({ token: userAccessToken })
-
- expect(body.total).to.equal(0)
- expect(body.data).to.have.lengthOf(0)
- })
-
- it('Should be able to search through videos in my history', async function () {
- const body = await server.history.list({ search: '2' })
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos[0].name).to.equal('video 2')
- })
-
- it('Should clear my history', async function () {
- await server.history.removeAll({ beforeDate: video3WatchedDate.toISOString() })
- })
-
- it('Should have my history cleared', async function () {
- const body = await server.history.list()
- expect(body.total).to.equal(1)
-
- const videos = body.data
- expect(videos[0].name).to.equal('video 3')
- })
-
- it('Should disable videos history', async function () {
- await server.users.updateMe({
- videosHistoryEnabled: false
- })
-
- await server.views.view({ id: video2UUID, token: server.accessToken, currentTime: 8 })
-
- const { data } = await server.history.list()
- expect(data[0].name).to.not.equal('video 2')
- })
-
- it('Should re-enable videos history', async function () {
- await server.users.updateMe({
- videosHistoryEnabled: true
- })
-
- await server.views.view({ id: video2UUID, token: server.accessToken, currentTime: 8 })
-
- const { data } = await server.history.list()
- expect(data[0].name).to.equal('video 2')
- })
-
- it('Should not clean old history', async function () {
- this.timeout(50000)
-
- await killallServers([ server ])
-
- await server.run({ history: { videos: { max_age: '10 days' } } })
-
- await wait(6000)
-
- // Should still have history
-
- const body = await server.history.list()
- expect(body.total).to.equal(2)
- })
-
- it('Should clean old history', async function () {
- this.timeout(50000)
-
- await killallServers([ server ])
-
- await server.run({ history: { videos: { max_age: '5 seconds' } } })
-
- await wait(6000)
-
- const body = await server.history.list()
- expect(body.total).to.equal(0)
- })
-
- it('Should delete a specific history element', async function () {
- {
- await server.views.view({ id: video1UUID, token: server.accessToken, currentTime: 4 })
- await server.views.view({ id: video2UUID, token: server.accessToken, currentTime: 8 })
- }
-
- {
- const body = await server.history.list()
- expect(body.total).to.equal(2)
- }
-
- {
- await server.history.removeElement({ videoId: video1Id })
-
- const body = await server.history.list()
- expect(body.total).to.equal(1)
- expect(body.data[0].uuid).to.equal(video2UUID)
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/videos/videos-overview.ts b/server/tests/api/videos/videos-overview.ts
deleted file mode 100644
index f2496e35e..000000000
--- a/server/tests/api/videos/videos-overview.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { VideosOverview } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test a videos overview', function () {
- let server: PeerTubeServer = null
-
- function testOverviewCount (overview: VideosOverview, expected: number) {
- expect(overview.tags).to.have.lengthOf(expected)
- expect(overview.categories).to.have.lengthOf(expected)
- expect(overview.channels).to.have.lengthOf(expected)
- }
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- })
-
- it('Should send empty overview', async function () {
- const body = await server.overviews.getVideos({ page: 1 })
-
- testOverviewCount(body, 0)
- })
-
- it('Should upload 5 videos in a specific category, tag and channel but not include them in overview', async function () {
- this.timeout(60000)
-
- await wait(3000)
-
- await server.videos.upload({
- attributes: {
- name: 'video 0',
- category: 3,
- tags: [ 'coucou1', 'coucou2' ]
- }
- })
-
- const body = await server.overviews.getVideos({ page: 1 })
-
- testOverviewCount(body, 0)
- })
-
- it('Should upload another video and include all videos in the overview', async function () {
- this.timeout(120000)
-
- {
- for (let i = 1; i < 6; i++) {
- await server.videos.upload({
- attributes: {
- name: 'video ' + i,
- category: 3,
- tags: [ 'coucou1', 'coucou2' ]
- }
- })
- }
-
- await wait(3000)
- }
-
- {
- const body = await server.overviews.getVideos({ page: 1 })
-
- testOverviewCount(body, 1)
- }
-
- {
- const overview = await server.overviews.getVideos({ page: 2 })
-
- expect(overview.tags).to.have.lengthOf(1)
- expect(overview.categories).to.have.lengthOf(0)
- expect(overview.channels).to.have.lengthOf(0)
- }
- })
-
- it('Should have the correct overview', async function () {
- const overview1 = await server.overviews.getVideos({ page: 1 })
- const overview2 = await server.overviews.getVideos({ page: 2 })
-
- for (const arr of [ overview1.tags, overview1.categories, overview1.channels, overview2.tags ]) {
- expect(arr).to.have.lengthOf(1)
-
- const obj = arr[0]
-
- expect(obj.videos).to.have.lengthOf(6)
- expect(obj.videos[0].name).to.equal('video 5')
- expect(obj.videos[1].name).to.equal('video 4')
- expect(obj.videos[2].name).to.equal('video 3')
- expect(obj.videos[3].name).to.equal('video 2')
- expect(obj.videos[4].name).to.equal('video 1')
- expect(obj.videos[5].name).to.equal('video 0')
- }
-
- const tags = [ overview1.tags[0].tag, overview2.tags[0].tag ]
- expect(tags.find(t => t === 'coucou1')).to.not.be.undefined
- expect(tags.find(t => t === 'coucou2')).to.not.be.undefined
-
- expect(overview1.categories[0].category.id).to.equal(3)
-
- expect(overview1.channels[0].channel.name).to.equal('root_channel')
- })
-
- it('Should hide muted accounts', async function () {
- const token = await server.users.generateUserAndToken('choco')
-
- await server.blocklist.addToMyBlocklist({ token, account: 'root@' + server.host })
-
- {
- const body = await server.overviews.getVideos({ page: 1 })
-
- testOverviewCount(body, 1)
- }
-
- {
- const body = await server.overviews.getVideos({ page: 1, token })
-
- testOverviewCount(body, 0)
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/api/views/index.ts b/server/tests/api/views/index.ts
deleted file mode 100644
index 5e06b31fb..000000000
--- a/server/tests/api/views/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './video-views-counter'
-export * from './video-views-overall-stats'
-export * from './video-views-retention-stats'
-export * from './video-views-timeserie-stats'
-export * from './videos-views-cleaner'
diff --git a/server/tests/api/views/video-views-counter.ts b/server/tests/api/views/video-views-counter.ts
deleted file mode 100644
index 0c1b7859c..000000000
--- a/server/tests/api/views/video-views-counter.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { prepareViewsServers, prepareViewsVideos, processViewsBuffer } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import { cleanupTests, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
-
-describe('Test video views/viewers counters', function () {
- let servers: PeerTubeServer[]
-
- async function checkCounter (field: 'views' | 'viewers', id: string, expected: number) {
- for (const server of servers) {
- const video = await server.videos.get({ id })
-
- const messageSuffix = video.isLive
- ? 'live video'
- : 'vod video'
-
- expect(video[field]).to.equal(expected, `${field} not valid on server ${server.serverNumber} for ${messageSuffix} ${video.uuid}`)
- }
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await prepareViewsServers()
- })
-
- describe('Test views counter on VOD', function () {
- let videoUUID: string
-
- before(async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should not view a video if watch time is below the threshold', async function () {
- await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 2 ] })
- await processViewsBuffer(servers)
-
- await checkCounter('views', videoUUID, 0)
- })
-
- it('Should view a video if watch time is above the threshold', async function () {
- await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
- await processViewsBuffer(servers)
-
- await checkCounter('views', videoUUID, 1)
- })
-
- it('Should not view again this video with the same IP', async function () {
- await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
- await servers[0].views.simulateViewer({ id: videoUUID, xForwardedFor: '0.0.0.1,127.0.0.1', currentTimes: [ 1, 4 ] })
- await processViewsBuffer(servers)
-
- await checkCounter('views', videoUUID, 2)
- })
-
- it('Should view the video from server 2 and send the event', async function () {
- await servers[1].views.simulateViewer({ id: videoUUID, currentTimes: [ 1, 4 ] })
- await waitJobs(servers)
- await processViewsBuffer(servers)
-
- await checkCounter('views', videoUUID, 3)
- })
- })
-
- describe('Test views and viewers counters on live and VOD', function () {
- let liveVideoId: string
- let vodVideoId: string
- let command: FfmpegCommand
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
- })
-
- it('Should display no views and viewers', async function () {
- await checkCounter('views', liveVideoId, 0)
- await checkCounter('viewers', liveVideoId, 0)
-
- await checkCounter('views', vodVideoId, 0)
- await checkCounter('viewers', vodVideoId, 0)
- })
-
- it('Should view twice and display 1 view/viewer', async function () {
- this.timeout(30000)
-
- await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
- await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
- await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
- await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
-
- await waitJobs(servers)
- await checkCounter('viewers', liveVideoId, 1)
- await checkCounter('viewers', vodVideoId, 1)
-
- await processViewsBuffer(servers)
-
- await checkCounter('views', liveVideoId, 1)
- await checkCounter('views', vodVideoId, 1)
- })
-
- it('Should wait and display 0 viewers but still have 1 view', async function () {
- this.timeout(30000)
-
- await wait(12000)
- await waitJobs(servers)
-
- await checkCounter('views', liveVideoId, 1)
- await checkCounter('viewers', liveVideoId, 0)
-
- await checkCounter('views', vodVideoId, 1)
- await checkCounter('viewers', vodVideoId, 0)
- })
-
- it('Should view on a remote and on local and display 2 viewers and 3 views', async function () {
- this.timeout(30000)
-
- await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
- await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
- await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
-
- await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
- await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
- await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35 ] })
-
- await waitJobs(servers)
-
- await checkCounter('viewers', liveVideoId, 2)
- await checkCounter('viewers', vodVideoId, 2)
-
- await processViewsBuffer(servers)
-
- await checkCounter('views', liveVideoId, 3)
- await checkCounter('views', vodVideoId, 3)
- })
-
- after(async function () {
- await stopFfmpeg(command)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/views/video-views-overall-stats.ts b/server/tests/api/views/video-views-overall-stats.ts
deleted file mode 100644
index ac636961e..000000000
--- a/server/tests/api/views/video-views-overall-stats.ts
+++ /dev/null
@@ -1,368 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@server/tests/shared'
-import { cleanupTests, PeerTubeServer, stopFfmpeg, waitJobs } from '@shared/server-commands'
-import { wait } from '@shared/core-utils'
-import { VideoStatsOverall } from '@shared/models'
-
-/**
- *
- * Simulate 5 sections of viewers
- * * user0 started and ended before start date
- * * user1 started before start date and ended in the interval
- * * user2 started started in the interval and ended after end date
- * * user3 started and ended in the interval
- * * user4 started and ended after end date
- */
-async function simulateComplexViewers (servers: PeerTubeServer[], videoUUID: string) {
- const user0 = '8.8.8.8,127.0.0.1'
- const user1 = '8.8.8.8,127.0.0.1'
- const user2 = '8.8.8.9,127.0.0.1'
- const user3 = '8.8.8.10,127.0.0.1'
- const user4 = '8.8.8.11,127.0.0.1'
-
- await servers[0].views.view({ id: videoUUID, currentTime: 0, xForwardedFor: user0 }) // User 0 starts
- await wait(500)
-
- await servers[0].views.view({ id: videoUUID, currentTime: 0, xForwardedFor: user1 }) // User 1 starts
- await servers[0].views.view({ id: videoUUID, currentTime: 2, xForwardedFor: user0 }) // User 0 ends
- await wait(500)
-
- const startDate = new Date().toISOString()
- await servers[0].views.view({ id: videoUUID, currentTime: 0, xForwardedFor: user2 }) // User 2 starts
- await wait(500)
-
- await servers[0].views.view({ id: videoUUID, currentTime: 0, xForwardedFor: user3 }) // User 3 starts
- await wait(500)
-
- await servers[0].views.view({ id: videoUUID, currentTime: 4, xForwardedFor: user1 }) // User 1 ends
- await wait(500)
-
- await servers[0].views.view({ id: videoUUID, currentTime: 3, xForwardedFor: user3 }) // User 3 ends
- await wait(500)
-
- const endDate = new Date().toISOString()
- await servers[0].views.view({ id: videoUUID, currentTime: 0, xForwardedFor: user4 }) // User 4 starts
- await servers[0].views.view({ id: videoUUID, currentTime: 5, xForwardedFor: user2 }) // User 2 ends
- await wait(500)
-
- await servers[0].views.view({ id: videoUUID, currentTime: 1, xForwardedFor: user4 }) // User 4 ends
-
- await processViewersStats(servers)
-
- return { startDate, endDate }
-}
-
-describe('Test views overall stats', function () {
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await prepareViewsServers()
- })
-
- describe('Test watch time stats of local videos on live and VOD', function () {
- let vodVideoId: string
- let liveVideoId: string
- let command: FfmpegCommand
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
- })
-
- it('Should display overall stats of a video with no viewers', async function () {
- for (const videoId of [ liveVideoId, vodVideoId ]) {
- const stats = await servers[0].videoStats.getOverallStats({ videoId })
- const video = await servers[0].videos.get({ id: videoId })
-
- expect(video.views).to.equal(0)
- expect(stats.averageWatchTime).to.equal(0)
- expect(stats.totalWatchTime).to.equal(0)
- expect(stats.totalViewers).to.equal(0)
- }
- })
-
- it('Should display overall stats with 1 viewer below the watch time limit', async function () {
- this.timeout(60000)
-
- for (const videoId of [ liveVideoId, vodVideoId ]) {
- await servers[0].views.simulateViewer({ id: videoId, currentTimes: [ 0, 1 ] })
- }
-
- await processViewersStats(servers)
-
- for (const videoId of [ liveVideoId, vodVideoId ]) {
- const stats = await servers[0].videoStats.getOverallStats({ videoId })
- const video = await servers[0].videos.get({ id: videoId })
-
- expect(video.views).to.equal(0)
- expect(stats.averageWatchTime).to.equal(1)
- expect(stats.totalWatchTime).to.equal(1)
- expect(stats.totalViewers).to.equal(1)
- }
- })
-
- it('Should display overall stats with 2 viewers', async function () {
- this.timeout(60000)
-
- {
- await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 3 ] })
- await servers[0].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 35, 40 ] })
-
- await processViewersStats(servers)
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
- const video = await servers[0].videos.get({ id: vodVideoId })
-
- expect(video.views).to.equal(1)
- expect(stats.averageWatchTime).to.equal(2)
- expect(stats.totalWatchTime).to.equal(4)
- expect(stats.totalViewers).to.equal(2)
- }
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
- const video = await servers[0].videos.get({ id: liveVideoId })
-
- expect(video.views).to.equal(1)
- expect(stats.averageWatchTime).to.equal(21)
- expect(stats.totalWatchTime).to.equal(41)
- expect(stats.totalViewers).to.equal(2)
- }
- }
- })
-
- it('Should display overall stats with a remote viewer below the watch time limit', async function () {
- this.timeout(60000)
-
- for (const videoId of [ liveVideoId, vodVideoId ]) {
- await servers[1].views.simulateViewer({ id: videoId, currentTimes: [ 0, 2 ] })
- }
-
- await processViewersStats(servers)
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
- const video = await servers[0].videos.get({ id: vodVideoId })
-
- expect(video.views).to.equal(1)
- expect(stats.averageWatchTime).to.equal(2)
- expect(stats.totalWatchTime).to.equal(6)
- expect(stats.totalViewers).to.equal(3)
- }
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
- const video = await servers[0].videos.get({ id: liveVideoId })
-
- expect(video.views).to.equal(1)
- expect(stats.averageWatchTime).to.equal(14)
- expect(stats.totalWatchTime).to.equal(43)
- expect(stats.totalViewers).to.equal(3)
- }
- })
-
- it('Should display overall stats with a remote viewer above the watch time limit', async function () {
- this.timeout(60000)
-
- await servers[1].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 5 ] })
- await servers[1].views.simulateViewer({ id: liveVideoId, currentTimes: [ 0, 45 ] })
- await processViewersStats(servers)
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId })
- const video = await servers[0].videos.get({ id: vodVideoId })
-
- expect(video.views).to.equal(2)
- expect(stats.averageWatchTime).to.equal(3)
- expect(stats.totalWatchTime).to.equal(11)
- expect(stats.totalViewers).to.equal(4)
- }
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId })
- const video = await servers[0].videos.get({ id: liveVideoId })
-
- expect(video.views).to.equal(2)
- expect(stats.averageWatchTime).to.equal(22)
- expect(stats.totalWatchTime).to.equal(88)
- expect(stats.totalViewers).to.equal(4)
- }
- })
-
- it('Should filter overall stats by date', async function () {
- this.timeout(60000)
-
- const beforeView = new Date()
-
- await servers[0].views.simulateViewer({ id: vodVideoId, currentTimes: [ 0, 3 ] })
- await processViewersStats(servers)
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: vodVideoId, startDate: beforeView.toISOString() })
- expect(stats.averageWatchTime).to.equal(3)
- expect(stats.totalWatchTime).to.equal(3)
- expect(stats.totalViewers).to.equal(1)
- }
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: liveVideoId, endDate: beforeView.toISOString() })
- expect(stats.averageWatchTime).to.equal(22)
- expect(stats.totalWatchTime).to.equal(88)
- expect(stats.totalViewers).to.equal(4)
- }
- })
-
- after(async function () {
- await stopFfmpeg(command)
- })
- })
-
- describe('Test watchers peak stats of local videos on VOD', function () {
- let videoUUID: string
- let before2Watchers: Date
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId: videoUUID } = await prepareViewsVideos({ servers, live: true, vod: true }))
- })
-
- it('Should not have watchers peak', async function () {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
-
- expect(stats.viewersPeak).to.equal(0)
- expect(stats.viewersPeakDate).to.be.null
- })
-
- it('Should have watcher peak with 1 watcher', async function () {
- this.timeout(60000)
-
- const before = new Date()
- await servers[0].views.simulateViewer({ id: videoUUID, currentTimes: [ 0, 2 ] })
- const after = new Date()
-
- await processViewersStats(servers)
-
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
-
- expect(stats.viewersPeak).to.equal(1)
- expect(new Date(stats.viewersPeakDate)).to.be.above(before).and.below(after)
- })
-
- it('Should have watcher peak with 2 watchers', async function () {
- this.timeout(60000)
-
- before2Watchers = new Date()
- await servers[0].views.view({ id: videoUUID, currentTime: 0 })
- await servers[1].views.view({ id: videoUUID, currentTime: 0 })
- await servers[0].views.view({ id: videoUUID, currentTime: 2 })
- await servers[1].views.view({ id: videoUUID, currentTime: 2 })
- const after = new Date()
-
- await processViewersStats(servers)
-
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID })
-
- expect(stats.viewersPeak).to.equal(2)
- expect(new Date(stats.viewersPeakDate)).to.be.above(before2Watchers).and.below(after)
- })
-
- it('Should filter peak viewers stats by date', async function () {
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID, startDate: new Date().toISOString() })
- expect(stats.viewersPeak).to.equal(0)
- expect(stats.viewersPeakDate).to.not.exist
- }
-
- {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID, endDate: before2Watchers.toISOString() })
- expect(stats.viewersPeak).to.equal(1)
- expect(new Date(stats.viewersPeakDate)).to.be.below(before2Watchers)
- }
- })
-
- it('Should complex filter peak viewers by date', async function () {
- this.timeout(60000)
-
- const { startDate, endDate } = await simulateComplexViewers(servers, videoUUID)
-
- const expectCorrect = (stats: VideoStatsOverall) => {
- expect(stats.viewersPeak).to.equal(3)
- expect(new Date(stats.viewersPeakDate)).to.be.above(new Date(startDate)).and.below(new Date(endDate))
- }
-
- expectCorrect(await servers[0].videoStats.getOverallStats({ videoId: videoUUID, startDate, endDate }))
- expectCorrect(await servers[0].videoStats.getOverallStats({ videoId: videoUUID, startDate }))
- expectCorrect(await servers[0].videoStats.getOverallStats({ videoId: videoUUID, endDate }))
- expectCorrect(await servers[0].videoStats.getOverallStats({ videoId: videoUUID }))
- })
- })
-
- describe('Test countries', function () {
- let videoUUID: string
-
- it('Should not report countries if geoip is disabled', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- await waitJobs(servers)
-
- await servers[1].views.view({ id: uuid, xForwardedFor: '8.8.8.8,127.0.0.1', currentTime: 1 })
-
- await processViewersStats(servers)
-
- const stats = await servers[0].videoStats.getOverallStats({ videoId: uuid })
- expect(stats.countries).to.have.lengthOf(0)
- })
-
- it('Should report countries if geoip is enabled', async function () {
- this.timeout(240000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- videoUUID = uuid
- await waitJobs(servers)
-
- await Promise.all([
- servers[0].kill(),
- servers[1].kill()
- ])
-
- const config = { geo_ip: { enabled: true } }
- await Promise.all([
- servers[0].run(config),
- servers[1].run(config)
- ])
-
- await servers[0].views.view({ id: uuid, xForwardedFor: '8.8.8.8,127.0.0.1', currentTime: 1 })
- await servers[1].views.view({ id: uuid, xForwardedFor: '8.8.8.4,127.0.0.1', currentTime: 3 })
- await servers[1].views.view({ id: uuid, xForwardedFor: '80.67.169.12,127.0.0.1', currentTime: 2 })
-
- await processViewersStats(servers)
-
- const stats = await servers[0].videoStats.getOverallStats({ videoId: uuid })
- expect(stats.countries).to.have.lengthOf(2)
-
- expect(stats.countries[0].isoCode).to.equal('US')
- expect(stats.countries[0].viewers).to.equal(2)
-
- expect(stats.countries[1].isoCode).to.equal('FR')
- expect(stats.countries[1].viewers).to.equal(1)
- })
-
- it('Should filter countries stats by date', async function () {
- const stats = await servers[0].videoStats.getOverallStats({ videoId: videoUUID, startDate: new Date().toISOString() })
- expect(stats.countries).to.have.lengthOf(0)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/views/video-views-retention-stats.ts b/server/tests/api/views/video-views-retention-stats.ts
deleted file mode 100644
index 5b9ce4c92..000000000
--- a/server/tests/api/views/video-views-retention-stats.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@server/tests/shared'
-import { cleanupTests, PeerTubeServer } from '@shared/server-commands'
-
-describe('Test views retention stats', function () {
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await prepareViewsServers()
- })
-
- describe('Test retention stats on VOD', function () {
- let vodVideoId: string
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId } = await prepareViewsVideos({ servers, live: false, vod: true }))
- })
-
- it('Should display empty retention', async function () {
- const { data } = await servers[0].videoStats.getRetentionStats({ videoId: vodVideoId })
- expect(data).to.have.lengthOf(6)
-
- for (let i = 0; i < 6; i++) {
- expect(data[i].second).to.equal(i)
- expect(data[i].retentionPercent).to.equal(0)
- }
- })
-
- it('Should display appropriate retention metrics', async function () {
- await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] })
- await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 1, 3 ] })
- await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 4 ] })
- await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] })
-
- await processViewersStats(servers)
-
- const { data } = await servers[0].videoStats.getRetentionStats({ videoId: vodVideoId })
- expect(data).to.have.lengthOf(6)
-
- expect(data.map(d => d.retentionPercent)).to.deep.equal([ 50, 75, 25, 25, 25, 0 ])
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/views/video-views-timeserie-stats.ts b/server/tests/api/views/video-views-timeserie-stats.ts
deleted file mode 100644
index 2d991d7ea..000000000
--- a/server/tests/api/views/video-views-timeserie-stats.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@server/tests/shared'
-import { VideoStatsTimeserie, VideoStatsTimeserieMetric } from '@shared/models'
-import { cleanupTests, PeerTubeServer, stopFfmpeg } from '@shared/server-commands'
-
-function buildOneMonthAgo () {
- const monthAgo = new Date()
- monthAgo.setHours(0, 0, 0, 0)
-
- monthAgo.setDate(monthAgo.getDate() - 29)
-
- return monthAgo
-}
-
-describe('Test views timeserie stats', function () {
- const availableMetrics: VideoStatsTimeserieMetric[] = [ 'viewers' ]
-
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(120000)
-
- servers = await prepareViewsServers()
- })
-
- describe('Common metric tests', function () {
- let vodVideoId: string
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId } = await prepareViewsVideos({ servers, live: false, vod: true }))
- })
-
- it('Should display empty metric stats', async function () {
- for (const metric of availableMetrics) {
- const { data } = await servers[0].videoStats.getTimeserieStats({ videoId: vodVideoId, metric })
-
- expect(data).to.have.length.at.least(1)
-
- for (const d of data) {
- expect(d.value).to.equal(0)
- }
- }
- })
- })
-
- describe('Test viewer and watch time metrics on live and VOD', function () {
- let vodVideoId: string
- let liveVideoId: string
- let command: FfmpegCommand
-
- function expectTodayLastValue (result: VideoStatsTimeserie, lastValue?: number) {
- const { data } = result
-
- const last = data[data.length - 1]
- const today = new Date().getDate()
- expect(new Date(last.date).getDate()).to.equal(today)
-
- if (lastValue) expect(last.value).to.equal(lastValue)
- }
-
- function expectTimeserieData (result: VideoStatsTimeserie, lastValue: number) {
- const { data } = result
- expect(data).to.have.length.at.least(25)
-
- expectTodayLastValue(result, lastValue)
-
- for (let i = 0; i < data.length - 2; i++) {
- expect(data[i].value).to.equal(0)
- }
- }
-
- function expectInterval (result: VideoStatsTimeserie, intervalMs: number) {
- const first = result.data[0]
- const second = result.data[1]
- expect(new Date(second.date).getTime() - new Date(first.date).getTime()).to.equal(intervalMs)
- }
-
- before(async function () {
- this.timeout(240000);
-
- ({ vodVideoId, liveVideoId, ffmpegCommand: command } = await prepareViewsVideos({ servers, live: true, vod: true }))
- })
-
- it('Should display appropriate viewers metrics', async function () {
- for (const videoId of [ vodVideoId, liveVideoId ]) {
- await servers[0].views.simulateViewer({ id: videoId, currentTimes: [ 0, 3 ] })
- await servers[1].views.simulateViewer({ id: videoId, currentTimes: [ 0, 5 ] })
- }
-
- await processViewersStats(servers)
-
- for (const videoId of [ vodVideoId, liveVideoId ]) {
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId,
- startDate: buildOneMonthAgo(),
- endDate: new Date(),
- metric: 'viewers'
- })
- expectTimeserieData(result, 2)
- }
- })
-
- it('Should display appropriate watch time metrics', async function () {
- for (const videoId of [ vodVideoId, liveVideoId ]) {
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId,
- startDate: buildOneMonthAgo(),
- endDate: new Date(),
- metric: 'aggregateWatchTime'
- })
- expectTimeserieData(result, 8)
-
- await servers[1].views.simulateViewer({ id: videoId, currentTimes: [ 0, 1 ] })
- }
-
- await processViewersStats(servers)
-
- for (const videoId of [ vodVideoId, liveVideoId ]) {
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId,
- startDate: buildOneMonthAgo(),
- endDate: new Date(),
- metric: 'aggregateWatchTime'
- })
- expectTimeserieData(result, 9)
- }
- })
-
- it('Should use a custom start/end date', async function () {
- const now = new Date()
- const twentyDaysAgo = new Date()
- twentyDaysAgo.setDate(twentyDaysAgo.getDate() - 19)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: twentyDaysAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('1 day')
- expect(result.data).to.have.lengthOf(20)
-
- const first = result.data[0]
- expect(new Date(first.date).toLocaleDateString()).to.equal(twentyDaysAgo.toLocaleDateString())
-
- expectInterval(result, 24 * 3600 * 1000)
- expectTodayLastValue(result, 9)
- })
-
- it('Should automatically group by months', async function () {
- const now = new Date()
- const heightYearsAgo = new Date()
- heightYearsAgo.setFullYear(heightYearsAgo.getFullYear() - 7)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: heightYearsAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('6 months')
- expect(result.data).to.have.length.above(10).and.below(200)
- })
-
- it('Should automatically group by days', async function () {
- const now = new Date()
- const threeMonthsAgo = new Date()
- threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: threeMonthsAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('2 days')
- expect(result.data).to.have.length.above(10).and.below(200)
- })
-
- it('Should automatically group by hours', async function () {
- const now = new Date()
- const twoDaysAgo = new Date()
- twoDaysAgo.setDate(twoDaysAgo.getDate() - 1)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: twoDaysAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('1 hour')
- expect(result.data).to.have.length.above(24).and.below(50)
-
- expectInterval(result, 3600 * 1000)
- expectTodayLastValue(result, 9)
- })
-
- it('Should automatically group by ten minutes', async function () {
- const now = new Date()
- const twoHoursAgo = new Date()
- twoHoursAgo.setHours(twoHoursAgo.getHours() - 4)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: twoHoursAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('10 minutes')
- expect(result.data).to.have.length.above(20).and.below(30)
-
- expectInterval(result, 60 * 10 * 1000)
- expectTodayLastValue(result)
- })
-
- it('Should automatically group by one minute', async function () {
- const now = new Date()
- const thirtyAgo = new Date()
- thirtyAgo.setMinutes(thirtyAgo.getMinutes() - 30)
-
- const result = await servers[0].videoStats.getTimeserieStats({
- videoId: vodVideoId,
- metric: 'aggregateWatchTime',
- startDate: thirtyAgo,
- endDate: now
- })
-
- expect(result.groupInterval).to.equal('1 minute')
- expect(result.data).to.have.length.above(20).and.below(40)
-
- expectInterval(result, 60 * 1000)
- expectTodayLastValue(result)
- })
-
- after(async function () {
- await stopFfmpeg(command)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/api/views/videos-views-cleaner.ts b/server/tests/api/views/videos-views-cleaner.ts
deleted file mode 100644
index a84cd43c7..000000000
--- a/server/tests/api/views/videos-views-cleaner.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { SQLCommand } from '@server/tests/shared'
-import { wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test video views cleaner', function () {
- let servers: PeerTubeServer[]
- let sqlCommands: SQLCommand[] = []
-
- let videoIdServer1: string
- let videoIdServer2: string
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- videoIdServer1 = (await servers[0].videos.quickUpload({ name: 'video server 1' })).uuid
- videoIdServer2 = (await servers[1].videos.quickUpload({ name: 'video server 2' })).uuid
-
- await waitJobs(servers)
-
- await servers[0].views.simulateView({ id: videoIdServer1 })
- await servers[1].views.simulateView({ id: videoIdServer1 })
- await servers[0].views.simulateView({ id: videoIdServer2 })
- await servers[1].views.simulateView({ id: videoIdServer2 })
-
- await waitJobs(servers)
-
- sqlCommands = servers.map(s => new SQLCommand(s))
- })
-
- it('Should not clean old video views', async function () {
- this.timeout(50000)
-
- await killallServers([ servers[0] ])
-
- await servers[0].run({ views: { videos: { remote: { max_age: '10 days' } } } })
-
- await wait(6000)
-
- // Should still have views
-
- for (let i = 0; i < servers.length; i++) {
- const total = await sqlCommands[i].countVideoViewsOf(videoIdServer1)
- expect(total).to.equal(2, 'Server ' + servers[i].serverNumber + ' does not have the correct amount of views')
- }
-
- for (let i = 0; i < servers.length; i++) {
- const total = await sqlCommands[i].countVideoViewsOf(videoIdServer2)
- expect(total).to.equal(2, 'Server ' + servers[i].serverNumber + ' does not have the correct amount of views')
- }
- })
-
- it('Should clean old video views', async function () {
- this.timeout(50000)
-
- await killallServers([ servers[0] ])
-
- await servers[0].run({ views: { videos: { remote: { max_age: '5 seconds' } } } })
-
- await wait(6000)
-
- // Should still have views
-
- for (let i = 0; i < servers.length; i++) {
- const total = await sqlCommands[i].countVideoViewsOf(videoIdServer1)
- expect(total).to.equal(2)
- }
-
- const totalServer1 = await sqlCommands[0].countVideoViewsOf(videoIdServer2)
- expect(totalServer1).to.equal(0)
-
- const totalServer2 = await sqlCommands[1].countVideoViewsOf(videoIdServer2)
- expect(totalServer2).to.equal(2)
- })
-
- after(async function () {
- for (const sqlCommand of sqlCommands) {
- await sqlCommand.cleanup()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/cli/create-generate-storyboard-job.ts b/server/tests/cli/create-generate-storyboard-job.ts
deleted file mode 100644
index 02a4be8ae..000000000
--- a/server/tests/cli/create-generate-storyboard-job.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readdir, remove } from 'fs-extra'
-import { join } from 'path'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { SQLCommand } from '../shared'
-
-function listStoryboardFiles (server: PeerTubeServer) {
- const storage = server.getDirectoryPath('storyboards')
-
- return readdir(storage)
-}
-
-describe('Test create generate storyboard job', function () {
- let servers: PeerTubeServer[] = []
- const uuids: string[] = []
- let sql: SQLCommand
- let existingStoryboardName: string
-
- before(async function () {
- this.timeout(120000)
-
- // Run server 2 to have transcoding enabled
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- for (let i = 0; i < 3; i++) {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video ' + i })
- uuids.push(uuid)
- }
-
- await waitJobs(servers)
-
- const storage = servers[0].getDirectoryPath('storyboards')
- for (const storyboard of await listStoryboardFiles(servers[0])) {
- await remove(join(storage, storyboard))
- }
-
- sql = new SQLCommand(servers[0])
- await sql.deleteAll('storyboard')
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 4' })
- uuids.push(uuid)
-
- await waitJobs(servers)
-
- const storyboards = await listStoryboardFiles(servers[0])
- existingStoryboardName = storyboards[0]
- })
-
- it('Should create a storyboard of a video', async function () {
- this.timeout(120000)
-
- for (const uuid of [ uuids[0], uuids[3] ]) {
- const command = `npm run create-generate-storyboard-job -- -v ${uuid}`
- await servers[0].cli.execWithEnv(command)
- }
-
- await waitJobs(servers)
-
- {
- const storyboards = await listStoryboardFiles(servers[0])
- expect(storyboards).to.have.lengthOf(2)
- expect(storyboards).to.not.include(existingStoryboardName)
-
- existingStoryboardName = storyboards[0]
- }
-
- for (const server of servers) {
- for (const uuid of [ uuids[0], uuids[3] ]) {
- const { storyboards } = await server.storyboard.list({ id: uuid })
- expect(storyboards).to.have.lengthOf(1)
-
- await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
-
- it('Should create missing storyboards', async function () {
- this.timeout(120000)
-
- const command = `npm run create-generate-storyboard-job -- -a`
- await servers[0].cli.execWithEnv(command)
-
- await waitJobs(servers)
-
- {
- const storyboards = await listStoryboardFiles(servers[0])
- expect(storyboards).to.have.lengthOf(4)
- expect(storyboards).to.include(existingStoryboardName)
- }
-
- for (const server of servers) {
- for (const uuid of uuids) {
- const { storyboards } = await server.storyboard.list({ id: uuid })
- expect(storyboards).to.have.lengthOf(1)
-
- await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
-
- after(async function () {
- await sql.cleanup()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts
deleted file mode 100644
index edd727967..000000000
--- a/server/tests/cli/create-import-video-file-job.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoDetails, VideoFile, VideoInclude } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { expectStartWith } from '../shared'
-
-function assertVideoProperties (video: VideoFile, resolution: number, extname: string, size?: number) {
- expect(video).to.have.nested.property('resolution.id', resolution)
- expect(video).to.have.property('torrentUrl').that.includes(`-${resolution}.torrent`)
- expect(video).to.have.property('fileUrl').that.includes(`.${extname}`)
- expect(video).to.have.property('magnetUri').that.includes(`.${extname}`)
- expect(video).to.have.property('size').that.is.above(0)
-
- if (size) expect(video.size).to.equal(size)
-}
-
-async function checkFiles (video: VideoDetails, objectStorage: ObjectStorageCommand) {
- for (const file of video.files) {
- if (objectStorage) expectStartWith(file.fileUrl, objectStorage.getMockWebVideosBaseUrl())
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-}
-
-function runTests (enableObjectStorage: boolean) {
- let video1ShortId: string
- let video2UUID: string
-
- let servers: PeerTubeServer[] = []
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(90000)
-
- const config = enableObjectStorage
- ? objectStorage.getDefaultMockConfig()
- : {}
-
- // Run server 2 to have transcoding enabled
- servers = await createMultipleServers(2, config)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- if (enableObjectStorage) await objectStorage.prepareDefaultMockBuckets()
-
- // Upload two videos for our needs
- {
- const { shortUUID } = await servers[0].videos.upload({ attributes: { name: 'video1' } })
- video1ShortId = shortUUID
- }
-
- {
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video2' } })
- video2UUID = uuid
- }
-
- await waitJobs(servers)
-
- for (const server of servers) {
- await server.config.enableTranscoding()
- }
- })
-
- it('Should run a import job on video 1 with a lower resolution', async function () {
- const command = `npm run create-import-video-file-job -- -v ${video1ShortId} -i server/tests/fixtures/video_short_480.webm`
- await servers[0].cli.execWithEnv(command)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data: videos } = await server.videos.list()
- expect(videos).to.have.lengthOf(2)
-
- const video = videos.find(({ shortUUID }) => shortUUID === video1ShortId)
- const videoDetails = await server.videos.get({ id: video.shortUUID })
-
- expect(videoDetails.files).to.have.lengthOf(2)
- const [ originalVideo, transcodedVideo ] = videoDetails.files
- assertVideoProperties(originalVideo, 720, 'webm', 218910)
- assertVideoProperties(transcodedVideo, 480, 'webm', 69217)
-
- await checkFiles(videoDetails, enableObjectStorage && objectStorage)
- }
- })
-
- it('Should run a import job on video 2 with the same resolution and a different extension', async function () {
- const command = `npm run create-import-video-file-job -- -v ${video2UUID} -i server/tests/fixtures/video_short.ogv`
- await servers[1].cli.execWithEnv(command)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data: videos } = await server.videos.listWithToken({ include: VideoInclude.NOT_PUBLISHED_STATE })
- expect(videos).to.have.lengthOf(2)
-
- const video = videos.find(({ uuid }) => uuid === video2UUID)
- const videoDetails = await server.videos.get({ id: video.uuid })
-
- expect(videoDetails.files).to.have.lengthOf(4)
- const [ originalVideo, transcodedVideo420, transcodedVideo320, transcodedVideo240 ] = videoDetails.files
- assertVideoProperties(originalVideo, 720, 'ogv', 140849)
- assertVideoProperties(transcodedVideo420, 480, 'mp4')
- assertVideoProperties(transcodedVideo320, 360, 'mp4')
- assertVideoProperties(transcodedVideo240, 240, 'mp4')
-
- await checkFiles(videoDetails, enableObjectStorage && objectStorage)
- }
- })
-
- it('Should run a import job on video 2 with the same resolution and the same extension', async function () {
- const command = `npm run create-import-video-file-job -- -v ${video1ShortId} -i server/tests/fixtures/video_short2.webm`
- await servers[0].cli.execWithEnv(command)
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data: videos } = await server.videos.listWithToken({ include: VideoInclude.NOT_PUBLISHED_STATE })
- expect(videos).to.have.lengthOf(2)
-
- const video = videos.find(({ shortUUID }) => shortUUID === video1ShortId)
- const videoDetails = await server.videos.get({ id: video.uuid })
-
- expect(videoDetails.files).to.have.lengthOf(2)
- const [ video720, video480 ] = videoDetails.files
- assertVideoProperties(video720, 720, 'webm', 942961)
- assertVideoProperties(video480, 480, 'webm', 69217)
-
- await checkFiles(videoDetails, enableObjectStorage && objectStorage)
- }
- })
-
- it('Should not have run transcoding after an import job', async function () {
- const { data } = await servers[0].jobs.list({ jobType: 'video-transcoding' })
- expect(data).to.have.lengthOf(0)
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
-
- await cleanupTests(servers)
- })
-}
-
-describe('Test create import video jobs', function () {
-
- describe('On filesystem', function () {
- runTests(false)
- })
-
- describe('On object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- runTests(true)
- })
-})
diff --git a/server/tests/cli/create-move-video-storage-job.ts b/server/tests/cli/create-move-video-storage-job.ts
deleted file mode 100644
index fc6a8e648..000000000
--- a/server/tests/cli/create-move-video-storage-job.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { join } from 'path'
-import { areMockObjectStorageTestsDisabled } from '@shared/core-utils'
-import { HttpStatusCode, VideoDetails } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { checkDirectoryIsEmpty, expectStartWith } from '../shared'
-
-async function checkFiles (origin: PeerTubeServer, video: VideoDetails, objectStorage?: ObjectStorageCommand) {
- for (const file of video.files) {
- const start = objectStorage
- ? objectStorage.getMockWebVideosBaseUrl()
- : origin.url
-
- expectStartWith(file.fileUrl, start)
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-
- const start = objectStorage
- ? objectStorage.getMockPlaylistBaseUrl()
- : origin.url
-
- const hls = video.streamingPlaylists[0]
- expectStartWith(hls.playlistUrl, start)
- expectStartWith(hls.segmentsSha256Url, start)
-
- for (const file of hls.files) {
- expectStartWith(file.fileUrl, start)
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
-}
-
-describe('Test create move video storage job', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- let servers: PeerTubeServer[] = []
- const uuids: string[] = []
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- this.timeout(360000)
-
- // Run server 2 to have transcoding enabled
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].config.enableTranscoding()
-
- for (let i = 0; i < 3; i++) {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' + i } })
- uuids.push(uuid)
- }
-
- await waitJobs(servers)
-
- await servers[0].kill()
- await servers[0].run(objectStorage.getDefaultMockConfig())
- })
-
- it('Should move only one file', async function () {
- this.timeout(120000)
-
- const command = `npm run create-move-video-storage-job -- --to-object-storage -v ${uuids[1]}`
- await servers[0].cli.execWithEnv(command, objectStorage.getDefaultMockConfig())
- await waitJobs(servers)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuids[1] })
-
- await checkFiles(servers[0], video, objectStorage)
-
- for (const id of [ uuids[0], uuids[2] ]) {
- const video = await server.videos.get({ id })
-
- await checkFiles(servers[0], video)
- }
- }
- })
-
- it('Should move all files', async function () {
- this.timeout(120000)
-
- const command = `npm run create-move-video-storage-job -- --to-object-storage --all-videos`
- await servers[0].cli.execWithEnv(command, objectStorage.getDefaultMockConfig())
- await waitJobs(servers)
-
- for (const server of servers) {
- for (const id of [ uuids[0], uuids[2] ]) {
- const video = await server.videos.get({ id })
-
- await checkFiles(servers[0], video, objectStorage)
- }
- }
- })
-
- it('Should not have files on disk anymore', async function () {
- await checkDirectoryIsEmpty(servers[0], 'web-videos', [ 'private' ])
- await checkDirectoryIsEmpty(servers[0], join('web-videos', 'private'))
-
- await checkDirectoryIsEmpty(servers[0], join('streaming-playlists', 'hls'), [ 'private' ])
- await checkDirectoryIsEmpty(servers[0], join('streaming-playlists', 'hls', 'private'))
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts
deleted file mode 100644
index 94444ace3..000000000
--- a/server/tests/cli/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Order of the tests we want to execute
-import './create-import-video-file-job'
-import './create-generate-storyboard-job'
-import './create-move-video-storage-job'
-import './peertube'
-import './plugins'
-import './prune-storage'
-import './regenerate-thumbnails'
-import './reset-password'
-import './update-host'
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts
deleted file mode 100644
index ad14fde91..000000000
--- a/server/tests/cli/peertube.ts
+++ /dev/null
@@ -1,331 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { areHttpImportTestsDisabled, buildAbsoluteFixturePath } from '@shared/core-utils'
-import {
- cleanupTests,
- CLICommand,
- createSingleServer,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { FIXTURE_URLS, testHelloWorldRegisteredSettings } from '../shared'
-
-describe('Test CLI wrapper', function () {
- let server: PeerTubeServer
- let userAccessToken: string
-
- let cliCommand: CLICommand
-
- const cmd = 'node ./dist/server/tools/peertube.js'
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {
- rates_limit: {
- login: {
- max: 30
- }
- }
- })
- await setAccessTokensToServers([ server ])
-
- await server.users.create({ username: 'user_1', password: 'super_password' })
-
- userAccessToken = await server.login.getAccessToken({ username: 'user_1', password: 'super_password' })
-
- {
- const attributes = { name: 'user_channel', displayName: 'User channel', support: 'super support text' }
- await server.channels.create({ token: userAccessToken, attributes })
- }
-
- cliCommand = server.cli
- })
-
- describe('Authentication and instance selection', function () {
-
- it('Should get an access token', async function () {
- const stdout = await cliCommand.execWithEnv(`${cmd} token --url ${server.url} --username user_1 --password super_password`)
- const token = stdout.trim()
-
- const body = await server.users.getMyInfo({ token })
- expect(body.username).to.equal('user_1')
- })
-
- it('Should display no selected instance', async function () {
- this.timeout(60000)
-
- const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
- expect(stdout).to.contain('no instance selected')
- })
-
- it('Should add a user', async function () {
- this.timeout(60000)
-
- await cliCommand.execWithEnv(`${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
- })
-
- it('Should not fail to add a user if there is a slash at the end of the instance URL', async function () {
- this.timeout(60000)
-
- let fullServerURL = server.url + '/'
-
- await cliCommand.execWithEnv(`${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
-
- fullServerURL = server.url + '/asdfasdf'
- await cliCommand.execWithEnv(`${cmd} auth add -u ${fullServerURL} -U user_1 -p super_password`)
- })
-
- it('Should default to this user', async function () {
- this.timeout(60000)
-
- const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
- expect(stdout).to.contain(`instance ${server.url} selected`)
- })
-
- it('Should remember the user', async function () {
- this.timeout(60000)
-
- const stdout = await cliCommand.execWithEnv(`${cmd} auth list`)
- expect(stdout).to.contain(server.url)
- })
- })
-
- describe('Video upload/import', function () {
-
- it('Should upload a video', async function () {
- this.timeout(60000)
-
- const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
- const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
-
- await cliCommand.execWithEnv(`${cmd} upload ${params}`)
- })
-
- it('Should have the video uploaded', async function () {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(1)
-
- const video = await server.videos.get({ id: data[0].uuid })
- expect(video.name).to.equal('test upload')
- expect(video.support).to.equal('support_text')
- expect(video.channel.name).to.equal('user_channel')
- })
-
- it('Should import a video', async function () {
- if (areHttpImportTestsDisabled()) return
-
- this.timeout(60000)
-
- const params = `--target-url ${FIXTURE_URLS.youtube} --channel-name user_channel`
- await cliCommand.execWithEnv(`${cmd} import ${params}`)
- })
-
- it('Should have imported the video', async function () {
- if (areHttpImportTestsDisabled()) return
-
- this.timeout(60000)
-
- await waitJobs([ server ])
-
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
-
- const video = data.find(v => v.name === 'small video - youtube')
- expect(video).to.not.be.undefined
-
- const videoDetails = await server.videos.get({ id: video.id })
- expect(videoDetails.channel.name).to.equal('user_channel')
- expect(videoDetails.support).to.equal('super support text')
- expect(videoDetails.nsfw).to.be.false
- })
-
- it('Should not import again the same video', async function () {
- if (areHttpImportTestsDisabled()) return
-
- this.timeout(60000)
-
- const params = `--target-url ${FIXTURE_URLS.youtube} --channel-name user_channel`
- await cliCommand.execWithEnv(`${cmd} import ${params}`)
-
- await waitJobs([ server ])
-
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
-
- const videos = data.filter(v => v.name === 'small video - youtube')
- expect(videos).to.have.lengthOf(1)
-
- // So we can reimport it
- await server.videos.remove({ token: userAccessToken, id: videos[0].id })
- })
-
- it('Should import and override some imported attributes', async function () {
- if (areHttpImportTestsDisabled()) return
-
- this.timeout(60000)
-
- const params = `--target-url ${FIXTURE_URLS.youtube} ` +
- `--channel-name user_channel --video-name toto --nsfw --support support`
- await cliCommand.execWithEnv(`${cmd} import ${params}`)
-
- await waitJobs([ server ])
-
- {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
-
- const video = data.find(v => v.name === 'toto')
- expect(video).to.not.be.undefined
-
- const videoDetails = await server.videos.get({ id: video.id })
- expect(videoDetails.channel.name).to.equal('user_channel')
- expect(videoDetails.support).to.equal('support')
- expect(videoDetails.nsfw).to.be.true
- expect(videoDetails.commentsEnabled).to.be.true
- }
- })
- })
-
- describe('Admin auth', function () {
-
- it('Should remove the auth user', async function () {
- await cliCommand.execWithEnv(`${cmd} auth del ${server.url}`)
-
- const stdout = await cliCommand.execWithEnv(`${cmd} --help`)
- expect(stdout).to.contain('no instance selected')
- })
-
- it('Should add the admin user', async function () {
- await cliCommand.execWithEnv(`${cmd} auth add -u ${server.url} -U root -p test${server.internalServerNumber}`)
- })
- })
-
- describe('Manage plugins', function () {
-
- it('Should install a plugin', async function () {
- this.timeout(60000)
-
- await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world`)
- })
-
- it('Should have registered settings', async function () {
- await testHelloWorldRegisteredSettings(server)
- })
-
- it('Should list installed plugins', async function () {
- const res = await cliCommand.execWithEnv(`${cmd} plugins list`)
-
- expect(res).to.contain('peertube-plugin-hello-world')
- })
-
- it('Should uninstall the plugin', async function () {
- const res = await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
-
- expect(res).to.not.contain('peertube-plugin-hello-world')
- })
-
- it('Should install a plugin in requested version', async function () {
- this.timeout(60000)
-
- await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world --plugin-version 0.0.17`)
- })
-
- it('Should list installed plugins, in correct version', async function () {
- const res = await cliCommand.execWithEnv(`${cmd} plugins list`)
-
- expect(res).to.contain('peertube-plugin-hello-world')
- expect(res).to.contain('0.0.17')
- })
-
- it('Should uninstall the plugin again', async function () {
- const res = await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
-
- expect(res).to.not.contain('peertube-plugin-hello-world')
- })
-
- it('Should install a plugin in requested beta version', async function () {
- this.timeout(60000)
-
- await cliCommand.execWithEnv(`${cmd} plugins install --npm-name peertube-plugin-hello-world --plugin-version 0.0.21-beta.1`)
-
- const res = await cliCommand.execWithEnv(`${cmd} plugins list`)
-
- expect(res).to.contain('peertube-plugin-hello-world')
- expect(res).to.contain('0.0.21-beta.1')
-
- await cliCommand.execWithEnv(`${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
- })
- })
-
- describe('Manage video redundancies', function () {
- let anotherServer: PeerTubeServer
- let video1Server2: number
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(120000)
-
- anotherServer = await createSingleServer(2)
- await setAccessTokensToServers([ anotherServer ])
-
- await doubleFollow(server, anotherServer)
-
- servers = [ server, anotherServer ]
- await waitJobs(servers)
-
- const { uuid } = await anotherServer.videos.quickUpload({ name: 'super video' })
- await waitJobs(servers)
-
- video1Server2 = await server.videos.getId({ uuid })
- })
-
- it('Should add a redundancy', async function () {
- this.timeout(60000)
-
- const params = `add --video ${video1Server2}`
- await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
-
- await waitJobs(servers)
- })
-
- it('Should list redundancies', async function () {
- this.timeout(60000)
-
- {
- const params = 'list-my-redundancies'
- const stdout = await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
-
- expect(stdout).to.contain('super video')
- expect(stdout).to.contain(server.host)
- }
- })
-
- it('Should remove a redundancy', async function () {
- this.timeout(60000)
-
- const params = `remove --video ${video1Server2}`
- await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
-
- await waitJobs(servers)
-
- {
- const params = 'list-my-redundancies'
- const stdout = await cliCommand.execWithEnv(`${cmd} redundancy ${params}`)
-
- expect(stdout).to.not.contain('super video')
- }
- })
-
- after(async function () {
- await cleanupTests([ anotherServer ])
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/cli/plugins.ts b/server/tests/cli/plugins.ts
deleted file mode 100644
index c646e20d9..000000000
--- a/server/tests/cli/plugins.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test plugin scripts', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- })
-
- it('Should install a plugin from stateless CLI', async function () {
- this.timeout(60000)
-
- const packagePath = PluginsCommand.getPluginTestPath()
-
- await server.cli.execWithEnv(`npm run plugin:install -- --plugin-path ${packagePath}`)
- })
-
- it('Should install a theme from stateless CLI', async function () {
- this.timeout(60000)
-
- await server.cli.execWithEnv(`npm run plugin:install -- --npm-name peertube-theme-background-red`)
- })
-
- it('Should have the theme and the plugin registered when we restart peertube', async function () {
- this.timeout(30000)
-
- await killallServers([ server ])
- await server.run()
-
- const config = await server.config.getConfig()
-
- const plugin = config.plugin.registered
- .find(p => p.name === 'test')
- expect(plugin).to.not.be.undefined
-
- const theme = config.theme.registered
- .find(t => t.name === 'background-red')
- expect(theme).to.not.be.undefined
- })
-
- it('Should uninstall a plugin from stateless CLI', async function () {
- this.timeout(60000)
-
- await server.cli.execWithEnv(`npm run plugin:uninstall -- --npm-name peertube-plugin-test`)
- })
-
- it('Should have removed the plugin on another peertube restart', async function () {
- this.timeout(30000)
-
- await killallServers([ server ])
- await server.run()
-
- const config = await server.config.getConfig()
-
- const plugin = config.plugin.registered
- .find(p => p.name === 'test')
- expect(plugin).to.be.undefined
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts
deleted file mode 100644
index 72a4b1332..000000000
--- a/server/tests/cli/prune-storage.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { createFile, readdir } from 'fs-extra'
-import { join } from 'path'
-import { wait } from '@shared/core-utils'
-import { buildUUID } from '@shared/extra-utils'
-import { HttpStatusCode, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- CLICommand,
- createMultipleServers,
- doubleFollow,
- killallServers,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-async function assertNotExists (server: PeerTubeServer, directory: string, substring: string) {
- const files = await readdir(server.servers.buildDirectory(directory))
-
- for (const f of files) {
- expect(f).to.not.contain(substring)
- }
-}
-
-async function assertCountAreOkay (servers: PeerTubeServer[]) {
- for (const server of servers) {
- const videosCount = await server.servers.countFiles('web-videos')
- expect(videosCount).to.equal(9) // 2 videos with 4 resolutions + private directory
-
- const privateVideosCount = await server.servers.countFiles('web-videos/private')
- expect(privateVideosCount).to.equal(4)
-
- const torrentsCount = await server.servers.countFiles('torrents')
- expect(torrentsCount).to.equal(24)
-
- const previewsCount = await server.servers.countFiles('previews')
- expect(previewsCount).to.equal(3)
-
- const thumbnailsCount = await server.servers.countFiles('thumbnails')
- expect(thumbnailsCount).to.equal(5) // 3 local videos, 1 local playlist, 2 remotes videos (lazy downloaded) and 1 remote playlist
-
- const avatarsCount = await server.servers.countFiles('avatars')
- expect(avatarsCount).to.equal(4)
-
- const hlsRootCount = await server.servers.countFiles(join('streaming-playlists', 'hls'))
- expect(hlsRootCount).to.equal(3) // 2 videos + private directory
-
- const hlsPrivateRootCount = await server.servers.countFiles(join('streaming-playlists', 'hls', 'private'))
- expect(hlsPrivateRootCount).to.equal(1)
- }
-}
-
-describe('Test prune storage scripts', function () {
- let servers: PeerTubeServer[]
- const badNames: { [directory: string]: string[] } = {}
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2, { transcoding: { enabled: true } })
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- for (const server of servers) {
- await server.videos.upload({ attributes: { name: 'video 1', privacy: VideoPrivacy.PUBLIC } })
- await server.videos.upload({ attributes: { name: 'video 2', privacy: VideoPrivacy.PUBLIC } })
-
- await server.videos.upload({ attributes: { name: 'video 3', privacy: VideoPrivacy.PRIVATE } })
-
- await server.users.updateMyAvatar({ fixture: 'avatar.png' })
-
- await server.playlists.create({
- attributes: {
- displayName: 'playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: server.store.channel.id,
- thumbnailfile: 'custom-thumbnail.jpg'
- }
- })
- }
-
- await doubleFollow(servers[0], servers[1])
-
- // Lazy load the remote avatars
- {
- const account = await servers[0].accounts.get({ accountName: 'root@' + servers[1].host })
-
- for (const avatar of account.avatars) {
- await makeGetRequest({
- url: servers[0].url,
- path: avatar.path,
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- }
-
- {
- const account = await servers[1].accounts.get({ accountName: 'root@' + servers[0].host })
- for (const avatar of account.avatars) {
- await makeGetRequest({
- url: servers[1].url,
- path: avatar.path,
- expectedStatus: HttpStatusCode.OK_200
- })
- }
- }
-
- await wait(1000)
-
- await waitJobs(servers)
- await killallServers(servers)
-
- await wait(1000)
- })
-
- it('Should have the files on the disk', async function () {
- await assertCountAreOkay(servers)
- })
-
- it('Should create some dirty files', async function () {
- for (let i = 0; i < 2; i++) {
- {
- const basePublic = servers[0].servers.buildDirectory('web-videos')
- const basePrivate = servers[0].servers.buildDirectory(join('web-videos', 'private'))
-
- const n1 = buildUUID() + '.mp4'
- const n2 = buildUUID() + '.webm'
-
- await createFile(join(basePublic, n1))
- await createFile(join(basePublic, n2))
- await createFile(join(basePrivate, n1))
- await createFile(join(basePrivate, n2))
-
- badNames['web-videos'] = [ n1, n2 ]
- }
-
- {
- const base = servers[0].servers.buildDirectory('torrents')
-
- const n1 = buildUUID() + '-240.torrent'
- const n2 = buildUUID() + '-480.torrent'
-
- await createFile(join(base, n1))
- await createFile(join(base, n2))
-
- badNames['torrents'] = [ n1, n2 ]
- }
-
- {
- const base = servers[0].servers.buildDirectory('thumbnails')
-
- const n1 = buildUUID() + '.jpg'
- const n2 = buildUUID() + '.jpg'
-
- await createFile(join(base, n1))
- await createFile(join(base, n2))
-
- badNames['thumbnails'] = [ n1, n2 ]
- }
-
- {
- const base = servers[0].servers.buildDirectory('previews')
-
- const n1 = buildUUID() + '.jpg'
- const n2 = buildUUID() + '.jpg'
-
- await createFile(join(base, n1))
- await createFile(join(base, n2))
-
- badNames['previews'] = [ n1, n2 ]
- }
-
- {
- const base = servers[0].servers.buildDirectory('avatars')
-
- const n1 = buildUUID() + '.png'
- const n2 = buildUUID() + '.jpg'
-
- await createFile(join(base, n1))
- await createFile(join(base, n2))
-
- badNames['avatars'] = [ n1, n2 ]
- }
-
- {
- const directory = join('streaming-playlists', 'hls')
- const basePublic = servers[0].servers.buildDirectory(directory)
- const basePrivate = servers[0].servers.buildDirectory(join(directory, 'private'))
-
- const n1 = buildUUID()
- await createFile(join(basePublic, n1))
- await createFile(join(basePrivate, n1))
- badNames[directory] = [ n1 ]
- }
- }
- })
-
- it('Should run prune storage', async function () {
- this.timeout(30000)
-
- const env = servers[0].cli.getEnv()
- await CLICommand.exec(`echo y | ${env} npm run prune-storage`)
- })
-
- it('Should have removed files', async function () {
- await assertCountAreOkay(servers)
-
- for (const directory of Object.keys(badNames)) {
- for (const name of badNames[directory]) {
- await assertNotExists(servers[0], directory, name)
- }
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/cli/regenerate-thumbnails.ts b/server/tests/cli/regenerate-thumbnails.ts
deleted file mode 100644
index 66de7f79c..000000000
--- a/server/tests/cli/regenerate-thumbnails.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-import { expect } from 'chai'
-import { writeFile } from 'fs-extra'
-import { basename, join } from 'path'
-import { HttpStatusCode, Video } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '../../../shared/server-commands'
-
-async function testThumbnail (server: PeerTubeServer, videoId: number | string) {
- const video = await server.videos.get({ id: videoId })
-
- const requests = [
- makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 }),
- makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- ]
-
- for (const req of requests) {
- const res = await req
- expect(res.body).to.not.have.lengthOf(0)
- }
-}
-
-describe('Test regenerate thumbnails script', function () {
- let servers: PeerTubeServer[]
-
- let video1: Video
- let video2: Video
- let remoteVideo: Video
-
- let thumbnail1Path: string
- let thumbnailRemotePath: string
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- {
- const videoUUID1 = (await servers[0].videos.quickUpload({ name: 'video 1' })).uuid
- video1 = await servers[0].videos.get({ id: videoUUID1 })
-
- thumbnail1Path = join(servers[0].servers.buildDirectory('thumbnails'), basename(video1.thumbnailPath))
-
- const videoUUID2 = (await servers[0].videos.quickUpload({ name: 'video 2' })).uuid
- video2 = await servers[0].videos.get({ id: videoUUID2 })
- }
-
- {
- const videoUUID = (await servers[1].videos.quickUpload({ name: 'video 3' })).uuid
- await waitJobs(servers)
-
- remoteVideo = await servers[0].videos.get({ id: videoUUID })
-
- // Load remote thumbnail on disk
- await makeGetRequest({ url: servers[0].url, path: remoteVideo.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
-
- thumbnailRemotePath = join(servers[0].servers.buildDirectory('thumbnails'), basename(remoteVideo.thumbnailPath))
- }
-
- await writeFile(thumbnail1Path, '')
- await writeFile(thumbnailRemotePath, '')
- })
-
- it('Should have empty thumbnails', async function () {
- {
- const res = await makeGetRequest({ url: servers[0].url, path: video1.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.have.lengthOf(0)
- }
-
- {
- const res = await makeGetRequest({ url: servers[0].url, path: video2.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.not.have.lengthOf(0)
- }
-
- {
- const res = await makeGetRequest({ url: servers[0].url, path: remoteVideo.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.have.lengthOf(0)
- }
- })
-
- it('Should regenerate local thumbnails from the CLI', async function () {
- this.timeout(15000)
-
- await servers[0].cli.execWithEnv(`npm run regenerate-thumbnails`)
- })
-
- it('Should have generated new thumbnail files', async function () {
- await testThumbnail(servers[0], video1.uuid)
- await testThumbnail(servers[0], video2.uuid)
-
- const res = await makeGetRequest({ url: servers[0].url, path: remoteVideo.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.have.lengthOf(0)
- })
-
- it('Should have deleted old thumbnail files', async function () {
- {
- await makeGetRequest({ url: servers[0].url, path: video1.thumbnailPath, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
-
- {
- await makeGetRequest({ url: servers[0].url, path: video2.thumbnailPath, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
- }
-
- {
- const res = await makeGetRequest({ url: servers[0].url, path: remoteVideo.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.body).to.have.lengthOf(0)
- }
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/cli/reset-password.ts b/server/tests/cli/reset-password.ts
deleted file mode 100644
index 79892173b..000000000
--- a/server/tests/cli/reset-password.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { cleanupTests, CLICommand, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test reset password scripts', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(30000)
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.users.create({ username: 'user_1', password: 'super password' })
- })
-
- it('Should change the user password from CLI', async function () {
- this.timeout(60000)
-
- const env = server.cli.getEnv()
- await CLICommand.exec(`echo coucou | ${env} npm run reset-password -- -u user_1`)
-
- await server.login.login({ user: { username: 'user_1', password: 'coucou' } })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts
deleted file mode 100644
index 386c384e6..000000000
--- a/server/tests/cli/update-host.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { getAllFiles } from '@shared/core-utils'
-import {
- cleanupTests,
- createSingleServer,
- killallServers,
- makeActivityPubGetRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { parseTorrentVideo } from '../shared'
-
-describe('Test update host scripts', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(60000)
-
- const overrideConfig = {
- webserver: {
- port: 9256
- }
- }
- // Run server 2 to have transcoding enabled
- server = await createSingleServer(2, overrideConfig)
- await setAccessTokensToServers([ server ])
-
- // Upload two videos for our needs
- const { uuid: video1UUID } = await server.videos.upload()
- await server.videos.upload()
-
- // Create a user
- await server.users.create({ username: 'toto', password: 'coucou' })
-
- // Create channel
- const videoChannel = {
- name: 'second_channel',
- displayName: 'second video channel',
- description: 'super video channel description'
- }
- await server.channels.create({ attributes: videoChannel })
-
- // Create comments
- const text = 'my super first comment'
- await server.comments.createThread({ videoId: video1UUID, text })
-
- await waitJobs(server)
- })
-
- it('Should run update host', async function () {
- this.timeout(30000)
-
- await killallServers([ server ])
- // Run server with standard configuration
- await server.run()
-
- await server.cli.execWithEnv(`npm run update-host`)
- })
-
- it('Should have updated videos url', async function () {
- const { total, data } = await server.videos.list()
- expect(total).to.equal(2)
-
- for (const video of data) {
- const { body } = await makeActivityPubGetRequest(server.url, '/videos/watch/' + video.uuid)
-
- expect(body.id).to.equal('http://127.0.0.1:9002/videos/watch/' + video.uuid)
-
- const videoDetails = await server.videos.get({ id: video.uuid })
-
- expect(videoDetails.trackerUrls[0]).to.include(server.host)
- expect(videoDetails.streamingPlaylists[0].playlistUrl).to.include(server.host)
- expect(videoDetails.streamingPlaylists[0].segmentsSha256Url).to.include(server.host)
- }
- })
-
- it('Should have updated video channels url', async function () {
- const { data, total } = await server.channels.list({ sort: '-name' })
- expect(total).to.equal(3)
-
- for (const channel of data) {
- const { body } = await makeActivityPubGetRequest(server.url, '/video-channels/' + channel.name)
-
- expect(body.id).to.equal('http://127.0.0.1:9002/video-channels/' + channel.name)
- }
- })
-
- it('Should have updated accounts url', async function () {
- const body = await server.accounts.list()
- expect(body.total).to.equal(3)
-
- for (const account of body.data) {
- const usernameWithDomain = account.name
- const { body } = await makeActivityPubGetRequest(server.url, '/accounts/' + usernameWithDomain)
-
- expect(body.id).to.equal('http://127.0.0.1:9002/accounts/' + usernameWithDomain)
- }
- })
-
- it('Should have updated torrent hosts', async function () {
- this.timeout(30000)
-
- const { data } = await server.videos.list()
- expect(data).to.have.lengthOf(2)
-
- for (const video of data) {
- const videoDetails = await server.videos.get({ id: video.id })
- const files = getAllFiles(videoDetails)
-
- expect(files).to.have.lengthOf(8)
-
- for (const file of files) {
- expect(file.magnetUri).to.contain('127.0.0.1%3A9002%2Ftracker%2Fsocket')
- expect(file.magnetUri).to.contain('127.0.0.1%3A9002%2Fstatic%2F')
-
- const torrent = await parseTorrentVideo(server, file)
- const announceWS = torrent.announce.find(a => a === 'ws://127.0.0.1:9002/tracker/socket')
- expect(announceWS).to.not.be.undefined
-
- const announceHttp = torrent.announce.find(a => a === 'http://127.0.0.1:9002/tracker/announce')
- expect(announceHttp).to.not.be.undefined
-
- expect(torrent.urlList[0]).to.contain('http://127.0.0.1:9002/static/')
- }
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/client.ts b/server/tests/client.ts
deleted file mode 100644
index 68f3a1d14..000000000
--- a/server/tests/client.ts
+++ /dev/null
@@ -1,556 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { omit } from '@shared/core-utils'
-import {
- Account,
- HTMLServerConfig,
- HttpStatusCode,
- ServerConfig,
- VideoPlaylistCreateResult,
- VideoPlaylistPrivacy,
- VideoPrivacy
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- makeHTMLRequest,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '../../shared/server-commands'
-
-function checkIndexTags (html: string, title: string, description: string, css: string, config: ServerConfig) {
- expect(html).to.contain('' + title + '')
- expect(html).to.contain('')
- expect(html).to.contain('')
-
- const htmlConfig: HTMLServerConfig = omit(config, [ 'signup' ])
- const configObjectString = JSON.stringify(htmlConfig)
- const configEscapedString = JSON.stringify(configObjectString)
-
- expect(html).to.contain(``)
-}
-
-describe('Test a client controllers', function () {
- let servers: PeerTubeServer[] = []
- let account: Account
-
- const videoName = 'my super name for server 1'
- const videoDescription = 'my
super __description__ for *server* 1'
- const videoDescriptionPlainText = 'my super description for server 1'
-
- const playlistName = 'super playlist name'
- const playlistDescription = 'super playlist description'
- let playlist: VideoPlaylistCreateResult
-
- const channelDescription = 'my super channel description'
-
- const watchVideoBasePaths = [ '/videos/watch/', '/w/' ]
- const watchPlaylistBasePaths = [ '/videos/watch/playlist/', '/w/p/' ]
-
- let videoIds: (string | number)[] = []
- let privateVideoId: string
- let internalVideoId: string
- let unlistedVideoId: string
- let passwordProtectedVideoId: string
-
- let playlistIds: (string | number)[] = []
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await setDefaultVideoChannel(servers)
-
- await servers[0].channels.update({
- channelName: servers[0].store.channel.name,
- attributes: { description: channelDescription }
- })
-
- // Public video
-
- {
- const attributes = { name: videoName, description: videoDescription }
- await servers[0].videos.upload({ attributes })
-
- const { data } = await servers[0].videos.list()
- expect(data.length).to.equal(1)
-
- const video = data[0]
- servers[0].store.video = video
- videoIds = [ video.id, video.uuid, video.shortUUID ]
- }
-
- {
- ({ uuid: privateVideoId } = await servers[0].videos.quickUpload({ name: 'private', privacy: VideoPrivacy.PRIVATE }));
- ({ uuid: unlistedVideoId } = await servers[0].videos.quickUpload({ name: 'unlisted', privacy: VideoPrivacy.UNLISTED }));
- ({ uuid: internalVideoId } = await servers[0].videos.quickUpload({ name: 'internal', privacy: VideoPrivacy.INTERNAL }));
- ({ uuid: passwordProtectedVideoId } = await servers[0].videos.quickUpload({
- name: 'password protected',
- privacy: VideoPrivacy.PASSWORD_PROTECTED,
- videoPasswords: [ 'password' ]
- }))
- }
-
- // Playlist
-
- {
- const attributes = {
- displayName: playlistName,
- description: playlistDescription,
- privacy: VideoPlaylistPrivacy.PUBLIC,
- videoChannelId: servers[0].store.channel.id
- }
-
- playlist = await servers[0].playlists.create({ attributes })
- playlistIds = [ playlist.id, playlist.shortUUID, playlist.uuid ]
-
- await servers[0].playlists.addElement({ playlistId: playlist.shortUUID, attributes: { videoId: servers[0].store.video.id } })
- }
-
- // Account
-
- {
- await servers[0].users.updateMe({ description: 'my account description' })
-
- account = await servers[0].accounts.get({ accountName: `${servers[0].store.user.username}@${servers[0].host}` })
- }
-
- await waitJobs(servers)
- })
-
- describe('oEmbed', function () {
-
- it('Should have valid oEmbed discovery tags for videos', async function () {
- for (const basePath of watchVideoBasePaths) {
- for (const id of videoIds) {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: basePath + id,
- accept: 'text/html',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const expectedLink = ``
-
- expect(res.text).to.contain(expectedLink)
- }
- }
- })
-
- it('Should have valid oEmbed discovery tags for a playlist', async function () {
- for (const basePath of watchPlaylistBasePaths) {
- for (const id of playlistIds) {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: basePath + id,
- accept: 'text/html',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const expectedLink = ``
-
- expect(res.text).to.contain(expectedLink)
- }
- }
- })
- })
-
- describe('Open Graph', function () {
-
- async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- expect(text).to.contain('')
- expect(text).to.contain(``)
- }
-
- async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- expect(text).to.contain('')
- expect(text).to.contain(``)
- }
-
- async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- expect(text).to.contain('')
- expect(text).to.contain(``)
- }
-
- async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- expect(text).to.contain('')
- expect(text).to.contain(``)
- }
-
- it('Should have valid Open Graph tags on the account page', async function () {
- await accountPageTest('/accounts/' + servers[0].store.user.username)
- await accountPageTest('/a/' + servers[0].store.user.username)
- await accountPageTest('/@' + servers[0].store.user.username)
- })
-
- it('Should have valid Open Graph tags on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].store.channel.name)
- await channelPageTest('/c/' + servers[0].store.channel.name)
- await channelPageTest('/@' + servers[0].store.channel.name)
- })
-
- it('Should have valid Open Graph tags on the watch page', async function () {
- for (const path of watchVideoBasePaths) {
- for (const id of videoIds) {
- await watchVideoPageTest(path + id)
- }
- }
- })
-
- it('Should have valid Open Graph tags on the watch page with thread id Angular param', async function () {
- for (const path of watchVideoBasePaths) {
- for (const id of videoIds) {
- await watchVideoPageTest(path + id + ';threadId=1')
- }
- }
- })
-
- it('Should have valid Open Graph tags on the watch playlist page', async function () {
- for (const path of watchPlaylistBasePaths) {
- for (const id of playlistIds) {
- await watchPlaylistPageTest(path + id)
- }
- }
- })
- })
-
- describe('Twitter card', async function () {
-
- describe('Not whitelisted', function () {
-
- async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- }
-
- async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- }
-
- async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- }
-
- async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- expect(text).to.contain(``)
- expect(text).to.contain(``)
- }
-
- it('Should have valid twitter card on the watch video page', async function () {
- for (const path of watchVideoBasePaths) {
- for (const id of videoIds) {
- await watchVideoPageTest(path + id)
- }
- }
- })
-
- it('Should have valid twitter card on the watch playlist page', async function () {
- for (const path of watchPlaylistBasePaths) {
- for (const id of playlistIds) {
- await watchPlaylistPageTest(path + id)
- }
- }
- })
-
- it('Should have valid twitter card on the account page', async function () {
- await accountPageTest('/accounts/' + account.name)
- await accountPageTest('/a/' + account.name)
- await accountPageTest('/@' + account.name)
- })
-
- it('Should have valid twitter card on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].store.channel.name)
- await channelPageTest('/c/' + servers[0].store.channel.name)
- await channelPageTest('/@' + servers[0].store.channel.name)
- })
- })
-
- describe('Whitelisted', function () {
-
- before(async function () {
- const config = await servers[0].config.getCustomConfig()
- config.services.twitter = {
- username: '@Kuja',
- whitelisted: true
- }
-
- await servers[0].config.updateCustomConfig({ newCustomConfig: config })
- })
-
- async function accountPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- }
-
- async function channelPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- }
-
- async function watchVideoPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- }
-
- async function watchPlaylistPageTest (path: string) {
- const res = await makeGetRequest({ url: servers[0].url, path, accept: 'text/html', expectedStatus: HttpStatusCode.OK_200 })
- const text = res.text
-
- expect(text).to.contain('')
- expect(text).to.contain('')
- }
-
- it('Should have valid twitter card on the watch video page', async function () {
- for (const path of watchVideoBasePaths) {
- for (const id of videoIds) {
- await watchVideoPageTest(path + id)
- }
- }
- })
-
- it('Should have valid twitter card on the watch playlist page', async function () {
- for (const path of watchPlaylistBasePaths) {
- for (const id of playlistIds) {
- await watchPlaylistPageTest(path + id)
- }
- }
- })
-
- it('Should have valid twitter card on the account page', async function () {
- await accountPageTest('/accounts/' + account.name)
- await accountPageTest('/a/' + account.name)
- await accountPageTest('/@' + account.name)
- })
-
- it('Should have valid twitter card on the channel page', async function () {
- await channelPageTest('/video-channels/' + servers[0].store.channel.name)
- await channelPageTest('/c/' + servers[0].store.channel.name)
- await channelPageTest('/@' + servers[0].store.channel.name)
- })
- })
- })
-
- describe('Index HTML', function () {
-
- it('Should have valid index html tags (title, description...)', async function () {
- const config = await servers[0].config.getConfig()
- const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
-
- const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
- checkIndexTags(res.text, 'PeerTube', description, '', config)
- })
-
- it('Should update the customized configuration and have the correct index html tags', async function () {
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- instance: {
- name: 'PeerTube updated',
- shortDescription: 'my short description',
- description: 'my super description',
- terms: 'my super terms',
- defaultNSFWPolicy: 'blur',
- defaultClientRoute: '/videos/recently-added',
- customizations: {
- javascript: 'alert("coucou")',
- css: 'body { background-color: red; }'
- }
- }
- }
- })
-
- const config = await servers[0].config.getConfig()
- const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
-
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
- })
-
- it('Should have valid index html updated tags (title, description...)', async function () {
- const config = await servers[0].config.getConfig()
- const res = await makeHTMLRequest(servers[0].url, '/videos/trending')
-
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
- })
-
- it('Should use the original video URL for the canonical tag', async function () {
- for (const basePath of watchVideoBasePaths) {
- for (const id of videoIds) {
- const res = await makeHTMLRequest(servers[1].url, basePath + id)
- expect(res.text).to.contain(``)
- }
- }
- })
-
- it('Should use the original account URL for the canonical tag', async function () {
- const accountURLtest = res => {
- expect(res.text).to.contain(``)
- }
-
- accountURLtest(await makeHTMLRequest(servers[1].url, '/accounts/root@' + servers[0].host))
- accountURLtest(await makeHTMLRequest(servers[1].url, '/a/root@' + servers[0].host))
- accountURLtest(await makeHTMLRequest(servers[1].url, '/@root@' + servers[0].host))
- })
-
- it('Should use the original channel URL for the canonical tag', async function () {
- const channelURLtests = res => {
- expect(res.text).to.contain(``)
- }
-
- channelURLtests(await makeHTMLRequest(servers[1].url, '/video-channels/root_channel@' + servers[0].host))
- channelURLtests(await makeHTMLRequest(servers[1].url, '/c/root_channel@' + servers[0].host))
- channelURLtests(await makeHTMLRequest(servers[1].url, '/@root_channel@' + servers[0].host))
- })
-
- it('Should use the original playlist URL for the canonical tag', async function () {
- for (const basePath of watchPlaylistBasePaths) {
- for (const id of playlistIds) {
- const res = await makeHTMLRequest(servers[1].url, basePath + id)
- expect(res.text).to.contain(``)
- }
- }
- })
-
- it('Should add noindex meta tag for remote accounts', async function () {
- const handle = 'root@' + servers[0].host
- const paths = [ '/accounts/', '/a/', '/@' ]
-
- for (const path of paths) {
- {
- const { text } = await makeHTMLRequest(servers[1].url, path + handle)
- expect(text).to.contain('')
- }
-
- {
- const { text } = await makeHTMLRequest(servers[0].url, path + handle)
- expect(text).to.not.contain('')
- }
- }
- })
-
- it('Should add noindex meta tag for remote channels', async function () {
- const handle = 'root_channel@' + servers[0].host
- const paths = [ '/video-channels/', '/c/', '/@' ]
-
- for (const path of paths) {
- {
- const { text } = await makeHTMLRequest(servers[1].url, path + handle)
- expect(text).to.contain('')
- }
-
- {
- const { text } = await makeHTMLRequest(servers[0].url, path + handle)
- expect(text).to.not.contain('')
- }
- }
- })
-
- it('Should not display internal/private/password protected video', async function () {
- for (const basePath of watchVideoBasePaths) {
- for (const id of [ privateVideoId, internalVideoId, passwordProtectedVideoId ]) {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: basePath + id,
- accept: 'text/html',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
-
- expect(res.text).to.not.contain('internal')
- expect(res.text).to.not.contain('private')
- expect(res.text).to.not.contain('password protected')
- }
- }
- })
-
- it('Should add noindex meta tag for unlisted video', async function () {
- for (const basePath of watchVideoBasePaths) {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: basePath + unlistedVideoId,
- accept: 'text/html',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('unlisted')
- expect(res.text).to.contain('')
- }
- })
- })
-
- describe('Embed HTML', function () {
-
- it('Should have the correct embed html tags', async function () {
- const config = await servers[0].config.getConfig()
- const res = await makeHTMLRequest(servers[0].url, servers[0].store.video.embedPath)
-
- checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }', config)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/external-plugins/akismet.ts b/server/tests/external-plugins/akismet.ts
deleted file mode 100644
index e964bf0c2..000000000
--- a/server/tests/external-plugins/akismet.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Official plugin Akismet', function () {
- let servers: PeerTubeServer[]
- let videoUUID: string
-
- before(async function () {
- this.timeout(30000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await servers[0].plugins.install({
- npmName: 'peertube-plugin-akismet'
- })
-
- if (!process.env.AKISMET_KEY) throw new Error('Missing AKISMET_KEY from env')
-
- await servers[0].plugins.updateSettings({
- npmName: 'peertube-plugin-akismet',
- settings: {
- 'akismet-api-key': process.env.AKISMET_KEY
- }
- })
-
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Local threads/replies', function () {
-
- before(async function () {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
- videoUUID = uuid
- })
-
- it('Should not detect a thread as spam', async function () {
- await servers[0].comments.createThread({ videoId: videoUUID, text: 'comment' })
- })
-
- it('Should not detect a reply as spam', async function () {
- await servers[0].comments.addReplyToLastThread({ text: 'reply' })
- })
-
- it('Should detect a thread as spam', async function () {
- await servers[0].comments.createThread({
- videoId: videoUUID,
- text: 'akismet-guaranteed-spam',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should detect a thread as spam', async function () {
- await servers[0].comments.createThread({ videoId: videoUUID, text: 'comment' })
- await servers[0].comments.addReplyToLastThread({ text: 'akismet-guaranteed-spam', expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
- })
-
- describe('Remote threads/replies', function () {
-
- before(async function () {
- this.timeout(60000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video 1' })
- videoUUID = uuid
-
- await waitJobs(servers)
- })
-
- it('Should not detect a thread as spam', async function () {
- this.timeout(30000)
-
- await servers[1].comments.createThread({ videoId: videoUUID, text: 'remote comment 1' })
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should not detect a reply as spam', async function () {
- this.timeout(30000)
-
- await servers[1].comments.addReplyToLastThread({ text: 'I agree with you' })
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- expect(data).to.have.lengthOf(1)
-
- const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId: data[0].id })
- expect(tree.children).to.have.lengthOf(1)
- })
-
- it('Should detect a thread as spam', async function () {
- this.timeout(30000)
-
- await servers[1].comments.createThread({ videoId: videoUUID, text: 'akismet-guaranteed-spam' })
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should detect a thread as spam', async function () {
- this.timeout(30000)
-
- await servers[1].comments.addReplyToLastThread({ text: 'akismet-guaranteed-spam' })
- await waitJobs(servers)
-
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID })
- expect(data).to.have.lengthOf(1)
-
- const thread = data[0]
- const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId: thread.id })
- expect(tree.children).to.have.lengthOf(1)
- })
- })
-
- describe('Signup', function () {
-
- before(async function () {
- await servers[0].config.updateExistingSubConfig({
- newConfig: {
- signup: {
- enabled: true
- }
- }
- })
- })
-
- it('Should allow signup', async function () {
- await servers[0].registrations.register({
- username: 'user1',
- displayName: 'user 1'
- })
- })
-
- it('Should detect a signup as SPAM', async function () {
- await servers[0].registrations.register({
- username: 'user2',
- displayName: 'user 2',
- email: 'akismet-guaranteed-spam@example.com',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/external-plugins/auth-ldap.ts b/server/tests/external-plugins/auth-ldap.ts
deleted file mode 100644
index d51d337be..000000000
--- a/server/tests/external-plugins/auth-ldap.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Official plugin auth-ldap', function () {
- let server: PeerTubeServer
- let accessToken: string
- let userId: number
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ npmName: 'peertube-plugin-auth-ldap' })
- })
-
- it('Should not login with without LDAP settings', async function () {
- await server.login.login({ user: { username: 'fry', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not login with bad LDAP settings', async function () {
- await server.plugins.updateSettings({
- npmName: 'peertube-plugin-auth-ldap',
- settings: {
- 'bind-credentials': 'GoodNewsEveryone',
- 'bind-dn': 'cn=admin,dc=planetexpress,dc=com',
- 'insecure-tls': false,
- 'mail-property': 'mail',
- 'search-base': 'ou=people,dc=planetexpress,dc=com',
- 'search-filter': '(|(mail={{username}})(uid={{username}}))',
- 'url': 'ldap://127.0.0.1:390',
- 'username-property': 'uid'
- }
- })
-
- await server.login.login({ user: { username: 'fry', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not login with good LDAP settings but wrong username/password', async function () {
- await server.plugins.updateSettings({
- npmName: 'peertube-plugin-auth-ldap',
- settings: {
- 'bind-credentials': 'GoodNewsEveryone',
- 'bind-dn': 'cn=admin,dc=planetexpress,dc=com',
- 'insecure-tls': false,
- 'mail-property': 'mail',
- 'search-base': 'ou=people,dc=planetexpress,dc=com',
- 'search-filter': '(|(mail={{username}})(uid={{username}}))',
- 'url': 'ldap://127.0.0.1:10389',
- 'username-property': 'uid'
- }
- })
-
- await server.login.login({ user: { username: 'fry', password: 'bad password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.login.login({ user: { username: 'fryr', password: 'fry' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should login with the appropriate username/password', async function () {
- accessToken = await server.login.getAccessToken({ username: 'fry', password: 'fry' })
- })
-
- it('Should login with the appropriate email/password', async function () {
- accessToken = await server.login.getAccessToken({ username: 'fry@planetexpress.com', password: 'fry' })
- })
-
- it('Should login get my profile', async function () {
- const body = await server.users.getMyInfo({ token: accessToken })
- expect(body.username).to.equal('fry')
- expect(body.email).to.equal('fry@planetexpress.com')
-
- userId = body.id
- })
-
- it('Should upload a video', async function () {
- await server.videos.upload({ token: accessToken, attributes: { name: 'my super video' } })
- })
-
- it('Should not be able to login if the user is banned', async function () {
- await server.users.banUser({ userId })
-
- await server.login.login({
- user: { username: 'fry@planetexpress.com', password: 'fry' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should be able to login if the user is unbanned', async function () {
- await server.users.unbanUser({ userId })
-
- await server.login.login({ user: { username: 'fry@planetexpress.com', password: 'fry' } })
- })
-
- it('Should not be able to ask password reset', async function () {
- await server.users.askResetPassword({ email: 'fry@planetexpress.com', expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should not be able to ask email verification', async function () {
- await server.users.askSendVerifyEmail({ email: 'fry@planetexpress.com', expectedStatus: HttpStatusCode.CONFLICT_409 })
- })
-
- it('Should not login if the plugin is uninstalled', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-auth-ldap' })
-
- await server.login.login({
- user: { username: 'fry@planetexpress.com', password: 'fry' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/external-plugins/auto-block-videos.ts b/server/tests/external-plugins/auto-block-videos.ts
deleted file mode 100644
index 95d7a4b58..000000000
--- a/server/tests/external-plugins/auto-block-videos.ts
+++ /dev/null
@@ -1,167 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { Video } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { MockBlocklist } from '../shared'
-
-async function check (server: PeerTubeServer, videoUUID: string, exists = true) {
- const { data } = await server.videos.list()
-
- const video = data.find(v => v.uuid === videoUUID)
-
- if (exists) expect(video).to.not.be.undefined
- else expect(video).to.be.undefined
-}
-
-describe('Official plugin auto-block videos', function () {
- let servers: PeerTubeServer[]
- let blocklistServer: MockBlocklist
- let server1Videos: Video[] = []
- let server2Videos: Video[] = []
- let port: number
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- for (const server of servers) {
- await server.plugins.install({ npmName: 'peertube-plugin-auto-block-videos' })
- }
-
- blocklistServer = new MockBlocklist()
- port = await blocklistServer.initialize()
-
- await servers[0].videos.quickUpload({ name: 'video server 1' })
- await servers[1].videos.quickUpload({ name: 'video server 2' })
- await servers[1].videos.quickUpload({ name: 'video 2 server 2' })
- await servers[1].videos.quickUpload({ name: 'video 3 server 2' })
-
- {
- const { data } = await servers[0].videos.list()
- server1Videos = data.map(v => Object.assign(v, { url: servers[0].url + '/videos/watch/' + v.uuid }))
- }
-
- {
- const { data } = await servers[1].videos.list()
- server2Videos = data.map(v => Object.assign(v, { url: servers[1].url + '/videos/watch/' + v.uuid }))
- }
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should update plugin settings', async function () {
- await servers[0].plugins.updateSettings({
- npmName: 'peertube-plugin-auto-block-videos',
- settings: {
- 'blocklist-urls': `http://127.0.0.1:${port}/blocklist`,
- 'check-seconds-interval': 1
- }
- })
- })
-
- it('Should auto block a video', async function () {
- await check(servers[0], server2Videos[0].uuid, true)
-
- blocklistServer.replace({
- data: [
- {
- value: server2Videos[0].url
- }
- ]
- })
-
- await wait(2000)
-
- await check(servers[0], server2Videos[0].uuid, false)
- })
-
- it('Should have video in blacklists', async function () {
- const body = await servers[0].blacklist.list()
-
- const videoBlacklists = body.data
- expect(videoBlacklists).to.have.lengthOf(1)
- expect(videoBlacklists[0].reason).to.contains('Automatically blocked from auto block plugin')
- expect(videoBlacklists[0].video.name).to.equal(server2Videos[0].name)
- })
-
- it('Should not block a local video', async function () {
- await check(servers[0], server1Videos[0].uuid, true)
-
- blocklistServer.replace({
- data: [
- {
- value: server1Videos[0].url
- }
- ]
- })
-
- await wait(2000)
-
- await check(servers[0], server1Videos[0].uuid, true)
- })
-
- it('Should remove a video block', async function () {
- await check(servers[0], server2Videos[0].uuid, false)
-
- blocklistServer.replace({
- data: [
- {
- value: server2Videos[0].url,
- action: 'remove'
- }
- ]
- })
-
- await wait(2000)
-
- await check(servers[0], server2Videos[0].uuid, true)
- })
-
- it('Should auto block a video, manually unblock it and do not reblock it automatically', async function () {
- this.timeout(20000)
-
- const video = server2Videos[1]
-
- await check(servers[0], video.uuid, true)
-
- blocklistServer.replace({
- data: [
- {
- value: video.url,
- updatedAt: new Date().toISOString()
- }
- ]
- })
-
- await wait(2000)
-
- await check(servers[0], video.uuid, false)
-
- await servers[0].blacklist.remove({ videoId: video.uuid })
-
- await check(servers[0], video.uuid, true)
-
- await killallServers([ servers[0] ])
- await servers[0].run()
- await wait(2000)
-
- await check(servers[0], video.uuid, true)
- })
-
- after(async function () {
- await blocklistServer.terminate()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/external-plugins/auto-mute.ts b/server/tests/external-plugins/auto-mute.ts
deleted file mode 100644
index a9bf3c173..000000000
--- a/server/tests/external-plugins/auto-mute.ts
+++ /dev/null
@@ -1,216 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- makeGetRequest,
- PeerTubeServer,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { MockBlocklist } from '../shared'
-
-describe('Official plugin auto-mute', function () {
- const autoMuteListPath = '/plugins/auto-mute/router/api/v1/mute-list'
- let servers: PeerTubeServer[]
- let blocklistServer: MockBlocklist
- let port: number
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- for (const server of servers) {
- await server.plugins.install({ npmName: 'peertube-plugin-auto-mute' })
- }
-
- blocklistServer = new MockBlocklist()
- port = await blocklistServer.initialize()
-
- await servers[0].videos.quickUpload({ name: 'video server 1' })
- await servers[1].videos.quickUpload({ name: 'video server 2' })
-
- await doubleFollow(servers[0], servers[1])
- })
-
- it('Should update plugin settings', async function () {
- await servers[0].plugins.updateSettings({
- npmName: 'peertube-plugin-auto-mute',
- settings: {
- 'blocklist-urls': `http://127.0.0.1:${port}/blocklist`,
- 'check-seconds-interval': 1
- }
- })
- })
-
- it('Should add a server blocklist', async function () {
- blocklistServer.replace({
- data: [
- {
- value: servers[1].host
- }
- ]
- })
-
- await wait(2000)
-
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(1)
- })
-
- it('Should remove a server blocklist', async function () {
- blocklistServer.replace({
- data: [
- {
- value: servers[1].host,
- action: 'remove'
- }
- ]
- })
-
- await wait(2000)
-
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(2)
- })
-
- it('Should add an account blocklist', async function () {
- blocklistServer.replace({
- data: [
- {
- value: 'root@' + servers[1].host
- }
- ]
- })
-
- await wait(2000)
-
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(1)
- })
-
- it('Should remove an account blocklist', async function () {
- blocklistServer.replace({
- data: [
- {
- value: 'root@' + servers[1].host,
- action: 'remove'
- }
- ]
- })
-
- await wait(2000)
-
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(2)
- })
-
- it('Should auto mute an account, manually unmute it and do not remute it automatically', async function () {
- this.timeout(20000)
-
- const account = 'root@' + servers[1].host
-
- blocklistServer.replace({
- data: [
- {
- value: account,
- updatedAt: new Date().toISOString()
- }
- ]
- })
-
- await wait(2000)
-
- {
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(1)
- }
-
- await servers[0].blocklist.removeFromServerBlocklist({ account })
-
- {
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(2)
- }
-
- await killallServers([ servers[0] ])
- await servers[0].run()
- await wait(2000)
-
- {
- const { total } = await servers[0].videos.list()
- expect(total).to.equal(2)
- }
- })
-
- it('Should not expose the auto mute list', async function () {
- await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/auto-mute/router/api/v1/mute-list',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should enable auto mute list', async function () {
- await servers[0].plugins.updateSettings({
- npmName: 'peertube-plugin-auto-mute',
- settings: {
- 'blocklist-urls': '',
- 'check-seconds-interval': 1,
- 'expose-mute-list': true
- }
- })
-
- await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/auto-mute/router/api/v1/mute-list',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should mute an account on server 1, and server 2 auto mutes it', async function () {
- this.timeout(20000)
-
- await servers[1].plugins.updateSettings({
- npmName: 'peertube-plugin-auto-mute',
- settings: {
- 'blocklist-urls': 'http://' + servers[0].host + autoMuteListPath,
- 'check-seconds-interval': 1,
- 'expose-mute-list': false
- }
- })
-
- await servers[0].blocklist.addToServerBlocklist({ account: 'root@' + servers[1].host })
- await servers[0].blocklist.addToMyBlocklist({ server: servers[1].host })
-
- const res = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/auto-mute/router/api/v1/mute-list',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const data = res.body.data
- expect(data).to.have.lengthOf(1)
- expect(data[0].updatedAt).to.exist
- expect(data[0].value).to.equal('root@' + servers[1].host)
-
- await wait(2000)
-
- for (const server of servers) {
- const { total } = await server.videos.list()
- expect(total).to.equal(1)
- }
- })
-
- after(async function () {
- await blocklistServer.terminate()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/external-plugins/index.ts b/server/tests/external-plugins/index.ts
deleted file mode 100644
index 815bbf1da..000000000
--- a/server/tests/external-plugins/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import './akismet'
-import './auth-ldap'
-import './auto-block-videos'
-import './auto-mute'
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
deleted file mode 100644
index 1754ac466..000000000
--- a/server/tests/feeds/feeds.ts
+++ /dev/null
@@ -1,695 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import * as chai from 'chai'
-import { XMLParser, XMLValidator } from 'fast-xml-parser'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- createSingleServer,
- doubleFollow,
- makeGetRequest,
- makeRawRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers,
- setDefaultChannelAvatar,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-chai.use(require('chai-xml'))
-chai.use(require('chai-json-schema'))
-chai.config.includeStack = true
-
-const expect = chai.expect
-
-describe('Test syndication feeds', () => {
- let servers: PeerTubeServer[] = []
- let serverHLSOnly: PeerTubeServer
-
- let userAccessToken: string
- let rootAccountId: number
- let rootChannelId: number
-
- let userAccountId: number
- let userChannelId: number
- let userFeedToken: string
-
- let liveId: string
-
- before(async function () {
- this.timeout(120000)
-
- // Run servers
- servers = await createMultipleServers(2)
- serverHLSOnly = await createSingleServer(3, {
- transcoding: {
- enabled: true,
- web_videos: { enabled: false },
- hls: { enabled: true }
- }
- })
-
- await setAccessTokensToServers([ ...servers, serverHLSOnly ])
- await setDefaultChannelAvatar(servers[0])
- await setDefaultVideoChannel(servers)
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableLive({ allowReplay: false, transcoding: false })
-
- {
- const user = await servers[0].users.getMyInfo()
- rootAccountId = user.account.id
- rootChannelId = user.videoChannels[0].id
- }
-
- {
- userAccessToken = await servers[0].users.generateUserAndToken('john')
-
- const user = await servers[0].users.getMyInfo({ token: userAccessToken })
- userAccountId = user.account.id
- userChannelId = user.videoChannels[0].id
-
- const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken })
- userFeedToken = token.feedToken
- }
-
- {
- await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'user video' } })
- }
-
- {
- const attributes = {
- name: 'my super name for server 1',
- description: 'my super description for server 1',
- fixture: 'video_short.webm'
- }
- const { id } = await servers[0].videos.upload({ attributes })
-
- await servers[0].comments.createThread({ videoId: id, text: 'super comment 1' })
- await servers[0].comments.createThread({ videoId: id, text: 'super comment 2' })
- }
-
- {
- const attributes = { name: 'unlisted video', privacy: VideoPrivacy.UNLISTED }
- const { id } = await servers[0].videos.upload({ attributes })
-
- await servers[0].comments.createThread({ videoId: id, text: 'comment on unlisted video' })
- }
-
- {
- const attributes = { name: 'password protected video', privacy: VideoPrivacy.PASSWORD_PROTECTED, videoPasswords: [ 'password' ] }
- const { id } = await servers[0].videos.upload({ attributes })
-
- await servers[0].comments.createThread({ videoId: id, text: 'comment on password protected video' })
- }
-
- await serverHLSOnly.videos.upload({ attributes: { name: 'hls only video' } })
-
- await waitJobs([ ...servers, serverHLSOnly ])
-
- await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-podcast-custom-tags') })
- })
-
- describe('All feed', function () {
-
- it('Should be well formed XML (covers RSS 2.0 and ATOM 1.0 endpoints)', async function () {
- for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
- const rss = await servers[0].feed.getXML({ feed, ignoreCache: true })
- expect(rss).xml.to.be.valid()
-
- const atom = await servers[0].feed.getXML({ feed, format: 'atom', ignoreCache: true })
- expect(atom).xml.to.be.valid()
- }
- })
-
- it('Should be well formed XML (covers Podcast endpoint)', async function () {
- const podcast = await servers[0].feed.getPodcastXML({ ignoreCache: true, channelId: rootChannelId })
- expect(podcast).xml.to.be.valid()
- })
-
- it('Should be well formed JSON (covers JSON feed 1.0 endpoint)', async function () {
- for (const feed of [ 'video-comments' as 'video-comments', 'videos' as 'videos' ]) {
- const jsonText = await servers[0].feed.getJSON({ feed, ignoreCache: true })
- expect(JSON.parse(jsonText)).to.be.jsonSchema({ type: 'object' })
- }
- })
-
- it('Should serve the endpoint with a classic request', async function () {
- await makeGetRequest({
- url: servers[0].url,
- path: '/feeds/videos.xml',
- accept: 'application/xml',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should refuse to serve the endpoint without accept header', async function () {
- await makeGetRequest({ url: servers[0].url, path: '/feeds/videos.xml', expectedStatus: HttpStatusCode.NOT_ACCEPTABLE_406 })
- })
- })
-
- describe('Videos feed', function () {
-
- describe('Podcast feed', function () {
-
- it('Should contain a valid podcast:alternateEnclosure', async function () {
- // Since podcast feeds should only work on the server they originate on,
- // only test the first server where the videos reside
- const rss = await servers[0].feed.getPodcastXML({ ignoreCache: false, channelId: rootChannelId })
- expect(XMLValidator.validate(rss)).to.be.true
-
- const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
- const xmlDoc = parser.parse(rss)
-
- const itemGuid = xmlDoc.rss.channel.item.guid
- expect(itemGuid).to.exist
- expect(itemGuid['@_isPermaLink']).to.equal(true)
-
- const enclosure = xmlDoc.rss.channel.item.enclosure
- expect(enclosure).to.exist
- const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure']
- expect(alternateEnclosure).to.exist
-
- expect(alternateEnclosure['@_type']).to.equal('video/webm')
- expect(alternateEnclosure['@_length']).to.equal(218910)
- expect(alternateEnclosure['@_lang']).to.equal('zh')
- expect(alternateEnclosure['@_title']).to.equal('720p')
- expect(alternateEnclosure['@_default']).to.equal(true)
-
- expect(alternateEnclosure['podcast:source'][0]['@_uri']).to.contain('-720.webm')
- expect(alternateEnclosure['podcast:source'][0]['@_uri']).to.equal(enclosure['@_url'])
- expect(alternateEnclosure['podcast:source'][1]['@_uri']).to.contain('-720.torrent')
- expect(alternateEnclosure['podcast:source'][1]['@_contentType']).to.equal('application/x-bittorrent')
- expect(alternateEnclosure['podcast:source'][2]['@_uri']).to.contain('magnet:?')
- })
-
- it('Should contain a valid podcast:alternateEnclosure with HLS only', async function () {
- const rss = await serverHLSOnly.feed.getPodcastXML({ ignoreCache: false, channelId: rootChannelId })
- expect(XMLValidator.validate(rss)).to.be.true
-
- const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
- const xmlDoc = parser.parse(rss)
-
- const itemGuid = xmlDoc.rss.channel.item.guid
- expect(itemGuid).to.exist
- expect(itemGuid['@_isPermaLink']).to.equal(true)
-
- const enclosure = xmlDoc.rss.channel.item.enclosure
- const alternateEnclosure = xmlDoc.rss.channel.item['podcast:alternateEnclosure']
- expect(alternateEnclosure).to.exist
-
- expect(alternateEnclosure['@_type']).to.equal('application/x-mpegURL')
- expect(alternateEnclosure['@_lang']).to.equal('zh')
- expect(alternateEnclosure['@_title']).to.equal('HLS')
- expect(alternateEnclosure['@_default']).to.equal(true)
-
- expect(alternateEnclosure['podcast:source']['@_uri']).to.contain('-master.m3u8')
- expect(alternateEnclosure['podcast:source']['@_uri']).to.equal(enclosure['@_url'])
- })
-
- it('Should contain a valid podcast:socialInteract', async function () {
- const rss = await servers[0].feed.getPodcastXML({ ignoreCache: false, channelId: rootChannelId })
- expect(XMLValidator.validate(rss)).to.be.true
-
- const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
- const xmlDoc = parser.parse(rss)
-
- const item = xmlDoc.rss.channel.item
- const socialInteract = item['podcast:socialInteract']
- expect(socialInteract).to.exist
- expect(socialInteract['@_protocol']).to.equal('activitypub')
- expect(socialInteract['@_uri']).to.exist
- expect(socialInteract['@_accountUrl']).to.exist
- })
-
- it('Should contain a valid support custom tags for plugins', async function () {
- const rss = await servers[0].feed.getPodcastXML({ ignoreCache: false, channelId: userChannelId })
- expect(XMLValidator.validate(rss)).to.be.true
-
- const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
- const xmlDoc = parser.parse(rss)
-
- const fooTag = xmlDoc.rss.channel.fooTag
- expect(fooTag).to.exist
- expect(fooTag['@_bar']).to.equal('baz')
- expect(fooTag['#text']).to.equal(42)
-
- const bizzBuzzItem = xmlDoc.rss.channel['biz:buzzItem']
- expect(bizzBuzzItem).to.exist
-
- let nestedTag = bizzBuzzItem.nestedTag
- expect(nestedTag).to.exist
- expect(nestedTag).to.equal('example nested tag')
-
- const item = xmlDoc.rss.channel.item
- const fizzTag = item.fizzTag
- expect(fizzTag).to.exist
- expect(fizzTag['@_bar']).to.equal('baz')
- expect(fizzTag['#text']).to.equal(21)
-
- const bizzBuzz = item['biz:buzz']
- expect(bizzBuzz).to.exist
-
- nestedTag = bizzBuzz.nestedTag
- expect(nestedTag).to.exist
- expect(nestedTag).to.equal('example nested tag')
- })
-
- it('Should contain a valid podcast:liveItem for live streams', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].live.create({
- fields: {
- name: 'live-0',
- privacy: VideoPrivacy.PUBLIC,
- channelId: rootChannelId,
- permanentLive: false
- }
- })
- liveId = uuid
-
- const ffmpeg = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveId, copyCodecs: true, fixtureName: 'video_short.mp4' })
- await servers[0].live.waitUntilPublished({ videoId: liveId })
-
- const rss = await servers[0].feed.getPodcastXML({ ignoreCache: false, channelId: rootChannelId })
- expect(XMLValidator.validate(rss)).to.be.true
-
- const parser = new XMLParser({ parseAttributeValue: true, ignoreAttributes: false })
- const xmlDoc = parser.parse(rss)
- const liveItem = xmlDoc.rss.channel['podcast:liveItem']
- expect(liveItem.title).to.equal('live-0')
- expect(liveItem.guid['@_isPermaLink']).to.equal(false)
- expect(liveItem.guid['#text']).to.contain(`${uuid}_`)
- expect(liveItem['@_status']).to.equal('live')
-
- const enclosure = liveItem.enclosure
- const alternateEnclosure = liveItem['podcast:alternateEnclosure']
- expect(alternateEnclosure).to.exist
- expect(alternateEnclosure['@_type']).to.equal('application/x-mpegURL')
- expect(alternateEnclosure['@_title']).to.equal('HLS live stream')
- expect(alternateEnclosure['@_default']).to.equal(true)
-
- expect(alternateEnclosure['podcast:source']['@_uri']).to.contain('/master.m3u8')
- expect(alternateEnclosure['podcast:source']['@_uri']).to.equal(enclosure['@_url'])
-
- await stopFfmpeg(ffmpeg)
-
- await servers[0].live.waitUntilEnded({ videoId: liveId })
-
- await waitJobs(servers)
- })
- })
-
- describe('JSON feed', function () {
-
- it('Should contain a valid \'attachments\' object', async function () {
- for (const server of servers) {
- const json = await server.feed.getJSON({ feed: 'videos', ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(2)
- expect(jsonObj.items[0].attachments).to.exist
- expect(jsonObj.items[0].attachments.length).to.be.eq(1)
- expect(jsonObj.items[0].attachments[0].mime_type).to.be.eq('application/x-bittorrent')
- expect(jsonObj.items[0].attachments[0].size_in_bytes).to.be.eq(218910)
- expect(jsonObj.items[0].attachments[0].url).to.contain('720.torrent')
- }
- })
-
- it('Should filter by account', async function () {
- {
- const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: rootAccountId }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('my super name for server 1')
- expect(jsonObj.items[0].author.name).to.equal('Main root channel')
- }
-
- {
- const json = await servers[0].feed.getJSON({ feed: 'videos', query: { accountId: userAccountId }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('user video')
- expect(jsonObj.items[0].author.name).to.equal('Main john channel')
- }
-
- for (const server of servers) {
- {
- const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'root@' + servers[0].host }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('my super name for server 1')
- }
-
- {
- const json = await server.feed.getJSON({ feed: 'videos', query: { accountName: 'john@' + servers[0].host }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('user video')
- }
- }
- })
-
- it('Should filter by video channel', async function () {
- {
- const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: rootChannelId }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('my super name for server 1')
- expect(jsonObj.items[0].author.name).to.equal('Main root channel')
- }
-
- {
- const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: userChannelId }, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('user video')
- expect(jsonObj.items[0].author.name).to.equal('Main john channel')
- }
-
- for (const server of servers) {
- {
- const query = { videoChannelName: 'root_channel@' + servers[0].host }
- const json = await server.feed.getJSON({ feed: 'videos', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('my super name for server 1')
- }
-
- {
- const query = { videoChannelName: 'john_channel@' + servers[0].host }
- const json = await server.feed.getJSON({ feed: 'videos', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].title).to.equal('user video')
- }
- }
- })
-
- it('Should correctly have videos feed with HLS only', async function () {
- this.timeout(120000)
-
- const json = await serverHLSOnly.feed.getJSON({ feed: 'videos', ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1)
- expect(jsonObj.items[0].attachments).to.exist
- expect(jsonObj.items[0].attachments.length).to.be.eq(4)
-
- for (let i = 0; i < 4; i++) {
- expect(jsonObj.items[0].attachments[i].mime_type).to.be.eq('application/x-bittorrent')
- expect(jsonObj.items[0].attachments[i].size_in_bytes).to.be.greaterThan(0)
- expect(jsonObj.items[0].attachments[i].url).to.exist
- }
- })
-
- it('Should not display waiting live videos', async function () {
- const { uuid } = await servers[0].live.create({
- fields: {
- name: 'live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: rootChannelId
- }
- })
- liveId = uuid
-
- const json = await servers[0].feed.getJSON({ feed: 'videos', ignoreCache: true })
-
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(2)
- expect(jsonObj.items[0].title).to.equal('my super name for server 1')
- expect(jsonObj.items[1].title).to.equal('user video')
- })
-
- it('Should display published live videos', async function () {
- this.timeout(120000)
-
- const ffmpeg = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveId, copyCodecs: true, fixtureName: 'video_short.mp4' })
- await servers[0].live.waitUntilPublished({ videoId: liveId })
-
- const json = await servers[0].feed.getJSON({ feed: 'videos', ignoreCache: true })
-
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(3)
- expect(jsonObj.items[0].title).to.equal('live')
- expect(jsonObj.items[1].title).to.equal('my super name for server 1')
- expect(jsonObj.items[2].title).to.equal('user video')
-
- await stopFfmpeg(ffmpeg)
- })
-
- it('Should have the channel avatar as feed icon', async function () {
- const json = await servers[0].feed.getJSON({ feed: 'videos', query: { videoChannelId: rootChannelId }, ignoreCache: true })
-
- const jsonObj = JSON.parse(json)
- const imageUrl = jsonObj.icon
- expect(imageUrl).to.include('/lazy-static/avatars/')
- await makeRawRequest({ url: imageUrl, expectedStatus: HttpStatusCode.OK_200 })
- })
- })
- })
-
- describe('Video comments feed', function () {
-
- it('Should contain valid comments (covers JSON feed 1.0 endpoint) and not from unlisted/password protected videos', async function () {
- for (const server of servers) {
- const json = await server.feed.getJSON({ feed: 'video-comments', ignoreCache: true })
-
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(2)
- expect(jsonObj.items[0].content_html).to.contain('super comment 2
')
- expect(jsonObj.items[1].content_html).to.contain('super comment 1
')
- }
- })
-
- it('Should not list comments from muted accounts or instances', async function () {
- this.timeout(30000)
-
- const remoteHandle = 'root@' + servers[0].host
-
- await servers[1].blocklist.addToServerBlocklist({ account: remoteHandle })
-
- {
- const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(0)
- }
-
- await servers[1].blocklist.removeFromServerBlocklist({ account: remoteHandle })
-
- {
- const videoUUID = (await servers[1].videos.quickUpload({ name: 'server 2' })).uuid
- await waitJobs(servers)
- await servers[0].comments.createThread({ videoId: videoUUID, text: 'super comment' })
- await waitJobs(servers)
-
- const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(3)
- }
-
- await servers[1].blocklist.addToMyBlocklist({ account: remoteHandle })
-
- {
- const json = await servers[1].feed.getJSON({ feed: 'video-comments', ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(2)
- }
- })
- })
-
- describe('Video feed from my subscriptions', function () {
- let feeduserAccountId: number
- let feeduserFeedToken: string
-
- it('Should list no videos for a user with no videos and no subscriptions', async function () {
- const attr = { username: 'feeduser', password: 'password' }
- await servers[0].users.create({ username: attr.username, password: attr.password })
- const feeduserAccessToken = await servers[0].login.getAccessToken(attr)
-
- {
- const user = await servers[0].users.getMyInfo({ token: feeduserAccessToken })
- feeduserAccountId = user.account.id
- }
-
- {
- const token = await servers[0].users.getMyScopedTokens({ token: feeduserAccessToken })
- feeduserFeedToken = token.feedToken
- }
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: feeduserAccessToken })
- expect(body.total).to.equal(0)
-
- const query = { accountId: feeduserAccountId, token: feeduserFeedToken }
- const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
- }
- })
-
- it('Should fail with an invalid token', async function () {
- const query = { accountId: feeduserAccountId, token: 'toto' }
- await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
- })
-
- it('Should fail with a token of another user', async function () {
- const query = { accountId: feeduserAccountId, token: userFeedToken }
- await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
- })
-
- it('Should list no videos for a user with videos but no subscriptions', async function () {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: userAccessToken })
- expect(body.total).to.equal(0)
-
- const query = { accountId: userAccountId, token: userFeedToken }
- const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(0) // no subscription, it should not list the instance's videos but list 0 videos
- })
-
- it('Should list self videos for a user with a subscription to themselves', async function () {
- this.timeout(30000)
-
- await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'john_channel@' + servers[0].host })
- await waitJobs(servers)
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: userAccessToken })
- expect(body.total).to.equal(1)
- expect(body.data[0].name).to.equal('user video')
-
- const query = { accountId: userAccountId, token: userFeedToken }
- const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(1) // subscribed to self, it should not list the instance's videos but list john's
- }
- })
-
- it('Should list videos of a user\'s subscription', async function () {
- this.timeout(30000)
-
- await servers[0].subscriptions.add({ token: userAccessToken, targetUri: 'root_channel@' + servers[0].host })
- await waitJobs(servers)
-
- {
- const body = await servers[0].videos.listMySubscriptionVideos({ token: userAccessToken })
- expect(body.total).to.equal(2, 'there should be 2 videos part of the subscription')
-
- const query = { accountId: userAccountId, token: userFeedToken }
- const json = await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
- const jsonObj = JSON.parse(json)
- expect(jsonObj.items.length).to.be.equal(2) // subscribed to root, it should not list the instance's videos but list root/john's
- }
- })
-
- it('Should renew the token, and so have an invalid old token', async function () {
- await servers[0].users.renewMyScopedTokens({ token: userAccessToken })
-
- const query = { accountId: userAccountId, token: userFeedToken }
- await servers[0].feed.getJSON({ feed: 'subscriptions', query, expectedStatus: HttpStatusCode.FORBIDDEN_403, ignoreCache: true })
- })
-
- it('Should succeed with the new token', async function () {
- const token = await servers[0].users.getMyScopedTokens({ token: userAccessToken })
- userFeedToken = token.feedToken
-
- const query = { accountId: userAccountId, token: userFeedToken }
- await servers[0].feed.getJSON({ feed: 'subscriptions', query, ignoreCache: true })
- })
-
- })
-
- describe('Cache', function () {
- const uuids: string[] = []
-
- function doPodcastRequest () {
- return makeGetRequest({
- url: servers[0].url,
- path: '/feeds/podcast/videos.xml',
- query: { videoChannelId: servers[0].store.channel.id },
- accept: 'application/xml',
- expectedStatus: HttpStatusCode.OK_200
- })
- }
-
- function doVideosRequest (query: { [id: string]: string } = {}) {
- return makeGetRequest({
- url: servers[0].url,
- path: '/feeds/videos.xml',
- query,
- accept: 'application/xml',
- expectedStatus: HttpStatusCode.OK_200
- })
- }
-
- before(async function () {
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'cache 1' })
- uuids.push(uuid)
- }
-
- {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'cache 2' })
- uuids.push(uuid)
- }
- })
-
- it('Should serve the videos endpoint as a cached request', async function () {
- await doVideosRequest()
-
- const res = await doVideosRequest()
-
- expect(res.headers['x-api-cache-cached']).to.equal('true')
- })
-
- it('Should not serve the videos endpoint as a cached request', async function () {
- const res = await doVideosRequest({ v: '186' })
-
- expect(res.headers['x-api-cache-cached']).to.not.exist
- })
-
- it('Should invalidate the podcast feed cache after video deletion', async function () {
- await doPodcastRequest()
-
- {
- const res = await doPodcastRequest()
- expect(res.headers['x-api-cache-cached']).to.exist
- }
-
- await servers[0].videos.remove({ id: uuids[0] })
-
- {
- const res = await doPodcastRequest()
- expect(res.headers['x-api-cache-cached']).to.not.exist
- }
- })
-
- it('Should invalidate the podcast feed cache after video deletion, even after server restart', async function () {
- this.timeout(120000)
-
- await doPodcastRequest()
-
- {
- const res = await doPodcastRequest()
- expect(res.headers['x-api-cache-cached']).to.exist
- }
-
- await servers[0].kill()
- await servers[0].run()
-
- await servers[0].videos.remove({ id: uuids[1] })
-
- const res = await doPodcastRequest()
- expect(res.headers['x-api-cache-cached']).to.not.exist
- })
-
- })
-
- after(async function () {
- await servers[0].plugins.uninstall({ npmName: 'peertube-plugin-test-podcast-custom-tags' })
-
- await cleanupTests([ ...servers, serverHLSOnly ])
- })
-})
diff --git a/server/tests/feeds/index.ts b/server/tests/feeds/index.ts
deleted file mode 100644
index aa6236a91..000000000
--- a/server/tests/feeds/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-import './feeds'
diff --git a/server/tests/fixtures/60fps_720p_small.mp4 b/server/tests/fixtures/60fps_720p_small.mp4
deleted file mode 100644
index 74bf968a4..000000000
Binary files a/server/tests/fixtures/60fps_720p_small.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json b/server/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json
deleted file mode 100644
index 4e7bc3af5..000000000
--- a/server/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json
+++ /dev/null
@@ -1,93 +0,0 @@
-{
- "headers": {
- "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)",
- "host": "localhost",
- "date": "Mon, 22 Oct 2018 13:34:22 GMT",
- "accept-encoding": "gzip",
- "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=",
- "content-type": "application/activity+json",
- "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==\"",
- "content-length": "2815"
- },
- "body": {
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "sensitive": "as:sensitive",
- "movedTo": {
- "@id": "as:movedTo",
- "@type": "@id"
- },
- "Hashtag": "as:Hashtag",
- "ostatus": "http://ostatus.org#",
- "atomUri": "ostatus:atomUri",
- "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
- "conversation": "ostatus:conversation",
- "toot": "http://joinmastodon.org/ns#",
- "Emoji": "toot:Emoji",
- "focalPoint": {
- "@container": "@list",
- "@id": "toot:focalPoint"
- },
- "featured": {
- "@id": "toot:featured",
- "@type": "@id"
- },
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
- }
- ],
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity",
- "type": "Create",
- "actor": "http://localhost:3000/users/ronan2",
- "published": "2018-10-22T13:34:18Z",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "object": {
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "type": "Note",
- "summary": null,
- "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "published": "2018-10-22T13:34:18Z",
- "url": "http://localhost:3000/@ronan2/100939547203370948",
- "attributedTo": "http://localhost:3000/users/ronan2",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "sensitive": false,
- "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation",
- "content": "@ronan zergzerg
",
- "contentMap": {
- "en": "@ronan zergzerg
"
- },
- "attachment": [],
- "tag": [
- {
- "type": "Mention",
- "href": "http://localhost:9000/accounts/ronan",
- "name": "@ronan@localhost:9000"
- }
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "creator": "http://localhost:3000/users/ronan2#main-key",
- "created": "2018-10-22T13:34:19Z",
- "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q=="
- }
- }
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/bad-http-signature.json b/server/tests/fixtures/ap-json/mastodon/bad-http-signature.json
deleted file mode 100644
index 098597db0..000000000
--- a/server/tests/fixtures/ap-json/mastodon/bad-http-signature.json
+++ /dev/null
@@ -1,93 +0,0 @@
-{
- "headers": {
- "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)",
- "host": "localhost",
- "date": "Mon, 22 Oct 2018 13:34:22 GMT",
- "accept-encoding": "gzip",
- "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=",
- "content-type": "application/activity+json",
- "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==\"",
- "content-length": "2815"
- },
- "body": {
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "sensitive": "as:sensitive",
- "movedTo": {
- "@id": "as:movedTo",
- "@type": "@id"
- },
- "Hashtag": "as:Hashtag",
- "ostatus": "http://ostatus.org#",
- "atomUri": "ostatus:atomUri",
- "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
- "conversation": "ostatus:conversation",
- "toot": "http://joinmastodon.org/ns#",
- "Emoji": "toot:Emoji",
- "focalPoint": {
- "@container": "@list",
- "@id": "toot:focalPoint"
- },
- "featured": {
- "@id": "toot:featured",
- "@type": "@id"
- },
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
- }
- ],
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity",
- "type": "Create",
- "actor": "http://localhost:3000/users/ronan2",
- "published": "2018-10-22T13:34:18Z",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "object": {
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "type": "Note",
- "summary": null,
- "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "published": "2018-10-22T13:34:18Z",
- "url": "http://localhost:3000/@ronan2/100939547203370948",
- "attributedTo": "http://localhost:3000/users/ronan2",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "sensitive": false,
- "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation",
- "content": "@ronan zergzerg
",
- "contentMap": {
- "en": "@ronan zergzerg
"
- },
- "attachment": [],
- "tag": [
- {
- "type": "Mention",
- "href": "http://localhost:9000/accounts/ronan",
- "name": "@ronan@localhost:9000"
- }
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "creator": "http://localhost:3000/users/ronan2#main-key",
- "created": "2018-10-22T13:34:19Z",
- "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q=="
- }
- }
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/bad-public-key.json b/server/tests/fixtures/ap-json/mastodon/bad-public-key.json
deleted file mode 100644
index 73d18b3ad..000000000
--- a/server/tests/fixtures/ap-json/mastodon/bad-public-key.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "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"
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/create-bad-signature.json b/server/tests/fixtures/ap-json/mastodon/create-bad-signature.json
deleted file mode 100644
index 2cd037241..000000000
--- a/server/tests/fixtures/ap-json/mastodon/create-bad-signature.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "sensitive": "as:sensitive",
- "movedTo": {
- "@id": "as:movedTo",
- "@type": "@id"
- },
- "Hashtag": "as:Hashtag",
- "ostatus": "http://ostatus.org#",
- "atomUri": "ostatus:atomUri",
- "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
- "conversation": "ostatus:conversation",
- "toot": "http://joinmastodon.org/ns#",
- "Emoji": "toot:Emoji",
- "focalPoint": {
- "@container": "@list",
- "@id": "toot:focalPoint"
- },
- "featured": {
- "@id": "toot:featured",
- "@type": "@id"
- },
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
- }
- ],
- "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698/activity",
- "type": "Create",
- "actor": "http://localhost:3000/users/ronan2",
- "published": "2018-10-22T12:43:07Z",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "object": {
- "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698",
- "type": "Note",
- "summary": null,
- "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "published": "2018-10-22T12:43:07Z",
- "url": "http://localhost:3000/@ronan2/100939345950887698",
- "attributedTo": "http://localhost:3000/users/ronan2",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "sensitive": false,
- "atomUri": "http://localhost:3000/users/ronan2/statuses/100939345950887698",
- "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation",
- "content": "@ronan zerg
",
- "contentMap": {
- "en": "@ronan zerg
"
- },
- "attachment": [],
- "tag": [
- {
- "type": "Mention",
- "href": "http://localhost:9000/accounts/ronan",
- "name": "@ronan@localhost:9000"
- }
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "creator": "http://localhost:3000/users/ronan2#main-key",
- "created": "2018-10-22T12:43:08Z",
- "signatureValue": "Vgr8nA0agPr9TcA4BlX+MWhmuE+rBcoIJLpnPbm3E5SnOCXbgjEfEaTLqfuzzkKNsR3PBbkvi3YWK4/DxJ0zmpzSB7yy4NRzluQMVQHqJiFKXAX3Sr3fIrK24xkWW9/F207c1NpFajSGbgnFKBdtFE0e5VqwSrSoOJkZukZW/2ATSnsyzblieuUmvTWpD0PqpUOsynPjw+RqZnqPn0cjw1z2Dm7ZRt3trnyMTXFYZw5U/YuqMY2kpadD6vq780md8kXlJIylxG6ZrlO2jz9fJdnfuVq43d4QFNsBm1K1r2WtNqX+i+wiqh+u3PjF4pzXtl/a3hJOH18IfZnK7I21mQ=="
- }
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/create.json b/server/tests/fixtures/ap-json/mastodon/create.json
deleted file mode 100644
index 0be271bb8..000000000
--- a/server/tests/fixtures/ap-json/mastodon/create.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "sensitive": "as:sensitive",
- "movedTo": {
- "@id": "as:movedTo",
- "@type": "@id"
- },
- "Hashtag": "as:Hashtag",
- "ostatus": "http://ostatus.org#",
- "atomUri": "ostatus:atomUri",
- "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
- "conversation": "ostatus:conversation",
- "toot": "http://joinmastodon.org/ns#",
- "Emoji": "toot:Emoji",
- "focalPoint": {
- "@container": "@list",
- "@id": "toot:focalPoint"
- },
- "featured": {
- "@id": "toot:featured",
- "@type": "@id"
- },
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
- }
- ],
- "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698/activity",
- "type": "Create",
- "actor": "http://localhost:3000/users/ronan2",
- "published": "2018-10-22T12:43:07Z",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "object": {
- "id": "http://localhost:3000/users/ronan2/statuses/100939345950887698",
- "type": "Note",
- "summary": null,
- "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "published": "2018-10-22T12:43:07Z",
- "url": "http://localhost:3000/@ronan2/100939345950887698",
- "attributedTo": "http://localhost:3000/users/ronan2",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "sensitive": false,
- "atomUri": "http://localhost:3000/users/ronan2/statuses/100939345950887698",
- "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation",
- "content": "@ronan zerg
",
- "contentMap": {
- "en": "@ronan zerg
"
- },
- "attachment": [],
- "tag": [
- {
- "type": "Mention",
- "href": "http://localhost:9000/accounts/ronan",
- "name": "@ronan@localhost:9000"
- }
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "creator": "http://localhost:3000/users/ronan2#main-key",
- "created": "2018-10-22T12:43:08Z",
- "signatureValue": "VgR8nA0agPr9TcA4BlX+MWhmuE+rBcoIJLpnPbm3E5SnOCXbgjEfEaTLqfuzzkKNsR3PBbkvi3YWK4/DxJ0zmpzSB7yy4NRzluQMVQHqJiFKXAX3Sr3fIrK24xkWW9/F207c1NpFajSGbgnFKBdtFE0e5VqwSrSoOJkZukZW/2ATSnsyzblieuUmvTWpD0PqpUOsynPjw+RqZnqPn0cjw1z2Dm7ZRt3trnyMTXFYZw5U/YuqMY2kpadD6vq780md8kXlJIylxG6ZrlO2jz9fJdnfuVq43d4QFNsBm1K1r2WtNqX+i+wiqh+u3PjF4pzXtl/a3hJOH18IfZnK7I21mQ=="
- }
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/http-signature.json b/server/tests/fixtures/ap-json/mastodon/http-signature.json
deleted file mode 100644
index 4e7bc3af5..000000000
--- a/server/tests/fixtures/ap-json/mastodon/http-signature.json
+++ /dev/null
@@ -1,93 +0,0 @@
-{
- "headers": {
- "user-agent": "http.rb/3.3.0 (Mastodon/2.5.0; +http://localhost:3000/)",
- "host": "localhost",
- "date": "Mon, 22 Oct 2018 13:34:22 GMT",
- "accept-encoding": "gzip",
- "digest": "SHA-256=FEr5j2WSSfdEMcG3NTOXuGU0lUchfTJx4+BtUlWOwDk=",
- "content-type": "application/activity+json",
- "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==\"",
- "content-length": "2815"
- },
- "body": {
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- {
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
- "sensitive": "as:sensitive",
- "movedTo": {
- "@id": "as:movedTo",
- "@type": "@id"
- },
- "Hashtag": "as:Hashtag",
- "ostatus": "http://ostatus.org#",
- "atomUri": "ostatus:atomUri",
- "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
- "conversation": "ostatus:conversation",
- "toot": "http://joinmastodon.org/ns#",
- "Emoji": "toot:Emoji",
- "focalPoint": {
- "@container": "@list",
- "@id": "toot:focalPoint"
- },
- "featured": {
- "@id": "toot:featured",
- "@type": "@id"
- },
- "schema": "http://schema.org#",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
- }
- ],
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948/activity",
- "type": "Create",
- "actor": "http://localhost:3000/users/ronan2",
- "published": "2018-10-22T13:34:18Z",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "object": {
- "id": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "type": "Note",
- "summary": null,
- "inReplyTo": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "published": "2018-10-22T13:34:18Z",
- "url": "http://localhost:3000/@ronan2/100939547203370948",
- "attributedTo": "http://localhost:3000/users/ronan2",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public"
- ],
- "cc": [
- "http://localhost:3000/users/ronan2/followers",
- "http://localhost:9000/accounts/ronan"
- ],
- "sensitive": false,
- "atomUri": "http://localhost:3000/users/ronan2/statuses/100939547203370948",
- "inReplyToAtomUri": "http://localhost:9000/videos/watch/90e6f8ed-b369-423c-b0c8-f44e5350c752",
- "conversation": "tag:localhost:3000,2018-10-19:objectId=72:objectType=Conversation",
- "content": "@ronan zergzerg
",
- "contentMap": {
- "en": "@ronan zergzerg
"
- },
- "attachment": [],
- "tag": [
- {
- "type": "Mention",
- "href": "http://localhost:9000/accounts/ronan",
- "name": "@ronan@localhost:9000"
- }
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "creator": "http://localhost:3000/users/ronan2#main-key",
- "created": "2018-10-22T13:34:19Z",
- "signatureValue": "x+xL4l8ERziYVhwEafHJyBQOInvNZ0gV4ccYd9AtFYeGJagc8fY6jjjhbDRCD7yMhgTjBX69z20MXnDuwpmM6wej3dt1wLKdIyXVViO84nAlqFz7KmNxtk5lDnAVX/vttscT5YUFvw4dbPT2mQiEd1lKbaLftRiIPEomZpQ37+fUkQdcPrnhruPAISO/Sof1n1LFW4mYIffozteQSZBH6HaCVp+MRMIhdMi5e8w7PD48/cZz8D/EU8Vqi91FM76/3tMqg6nLqQ+8bq74Jvt2kzwZlIufe+I55QMpZOmF6hGIJEt+R0JXdjQbtgcELONmNj2dr8sAlzu7zKlAGuJ24Q=="
- }
- }
-}
diff --git a/server/tests/fixtures/ap-json/mastodon/public-key.json b/server/tests/fixtures/ap-json/mastodon/public-key.json
deleted file mode 100644
index b7b9b8308..000000000
--- a/server/tests/fixtures/ap-json/mastodon/public-key.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "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"
-}
diff --git a/server/tests/fixtures/ap-json/peertube/announce-without-context.json b/server/tests/fixtures/ap-json/peertube/announce-without-context.json
deleted file mode 100644
index cda1c514c..000000000
--- a/server/tests/fixtures/ap-json/peertube/announce-without-context.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "type": "Announce",
- "id": "http://127.0.0.1:9002/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05/announces/1",
- "actor": "http://127.0.0.1:9002/accounts/peertube",
- "object": "http://127.0.0.1:9002/videos/watch/997111d4-e8d8-4f45-99d3-857905785d05",
- "to": [
- "https://www.w3.org/ns/activitystreams#Public",
- "http://127.0.0.1:9002/accounts/peertube/followers",
- "http://127.0.0.1:9002/video-channels/root_channel/followers",
- "http://127.0.0.1:9002/accounts/root/followers"
- ],
- "cc": []
-}
diff --git a/server/tests/fixtures/ap-json/peertube/invalid-keys.json b/server/tests/fixtures/ap-json/peertube/invalid-keys.json
deleted file mode 100644
index 0544e96b9..000000000
--- a/server/tests/fixtures/ap-json/peertube/invalid-keys.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqjQGdH6D3naKmSbbr/Df\nEh1H42F3WlHYXuxKLkm5Bemjdde+GwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYO\nwAyc3Zoy7afPNa4bZXqhJ1Im41rMGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55s\nIkczDkseJuadTvG+A1e4uNY2lnRmVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/F\npP5S75TS5l1DfJQIq2lp8RwrH6FvGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM\n7mS7eP8zF8lKXYUu8cjIscKm+XqGmyRoPyw2Pp53tew29idRUocVQHGBnlNbpKdd\naQIDAQAB\n-----END PUBLIC KEY-----\n",
- "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-----"
-}
-
-
diff --git a/server/tests/fixtures/ap-json/peertube/keys.json b/server/tests/fixtures/ap-json/peertube/keys.json
deleted file mode 100644
index 1a7700865..000000000
--- a/server/tests/fixtures/ap-json/peertube/keys.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqjQGdH6D3naKmSbbr/Df\nEh1H42F3WlHYXuxKLkm5Bemjdde+GwHYdz5m3fcIWw3HTzfA+y9Of8epGdfSrtYO\nwAyc3Zoy7afPNa4bZXqhJ1Im41rMGieiCuUn4uTPPucIjC0gCkVwvuQr3Elbk55s\nIkczDkseJuadTvG+A1e4uNY2lnRmVhf4g5B90u6CLe2KdbPpifRoKlw9zaUBj4/F\npP5S75TS5l1DfJQIq2lp8RwrH6FvGKLnWlbGeNYX96DDvlA5Sxoxz6a+bTV9OopM\n7mS7eP8zF8lKXYUu8cjIscKm+XqGmyRoPyw3Pp53tew29idRUocVQHGBnlNbpKdd\naQIDAQAB\n-----END PUBLIC KEY-----\n",
- "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-----"
-}
diff --git a/server/tests/fixtures/avatar-big.png b/server/tests/fixtures/avatar-big.png
deleted file mode 100644
index e593e40da..000000000
Binary files a/server/tests/fixtures/avatar-big.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar-resized-120x120.gif b/server/tests/fixtures/avatar-resized-120x120.gif
deleted file mode 100644
index 81a82189e..000000000
Binary files a/server/tests/fixtures/avatar-resized-120x120.gif and /dev/null differ
diff --git a/server/tests/fixtures/avatar-resized-120x120.png b/server/tests/fixtures/avatar-resized-120x120.png
deleted file mode 100644
index 9d84151f8..000000000
Binary files a/server/tests/fixtures/avatar-resized-120x120.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar-resized-48x48.gif b/server/tests/fixtures/avatar-resized-48x48.gif
deleted file mode 100644
index 5900ff12e..000000000
Binary files a/server/tests/fixtures/avatar-resized-48x48.gif and /dev/null differ
diff --git a/server/tests/fixtures/avatar-resized-48x48.png b/server/tests/fixtures/avatar-resized-48x48.png
deleted file mode 100644
index 9e5f3b490..000000000
Binary files a/server/tests/fixtures/avatar-resized-48x48.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar.gif b/server/tests/fixtures/avatar.gif
deleted file mode 100644
index f29707760..000000000
Binary files a/server/tests/fixtures/avatar.gif and /dev/null differ
diff --git a/server/tests/fixtures/avatar.png b/server/tests/fixtures/avatar.png
deleted file mode 100644
index 4b7fd2c0a..000000000
Binary files a/server/tests/fixtures/avatar.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar2-resized-120x120.png b/server/tests/fixtures/avatar2-resized-120x120.png
deleted file mode 100644
index 44149facb..000000000
Binary files a/server/tests/fixtures/avatar2-resized-120x120.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar2-resized-48x48.png b/server/tests/fixtures/avatar2-resized-48x48.png
deleted file mode 100644
index bb3939b1a..000000000
Binary files a/server/tests/fixtures/avatar2-resized-48x48.png and /dev/null differ
diff --git a/server/tests/fixtures/avatar2.png b/server/tests/fixtures/avatar2.png
deleted file mode 100644
index dae702190..000000000
Binary files a/server/tests/fixtures/avatar2.png and /dev/null differ
diff --git a/server/tests/fixtures/banner-resized.jpg b/server/tests/fixtures/banner-resized.jpg
deleted file mode 100644
index 952732d61..000000000
Binary files a/server/tests/fixtures/banner-resized.jpg and /dev/null differ
diff --git a/server/tests/fixtures/banner.jpg b/server/tests/fixtures/banner.jpg
deleted file mode 100644
index e5f284f59..000000000
Binary files a/server/tests/fixtures/banner.jpg and /dev/null differ
diff --git a/server/tests/fixtures/custom-preview-big.png b/server/tests/fixtures/custom-preview-big.png
deleted file mode 100644
index 03d171af3..000000000
Binary files a/server/tests/fixtures/custom-preview-big.png and /dev/null differ
diff --git a/server/tests/fixtures/custom-preview.jpg b/server/tests/fixtures/custom-preview.jpg
deleted file mode 100644
index 5a039d830..000000000
Binary files a/server/tests/fixtures/custom-preview.jpg and /dev/null differ
diff --git a/server/tests/fixtures/custom-thumbnail-big.jpg b/server/tests/fixtures/custom-thumbnail-big.jpg
deleted file mode 100644
index 08375e425..000000000
Binary files a/server/tests/fixtures/custom-thumbnail-big.jpg and /dev/null differ
diff --git a/server/tests/fixtures/custom-thumbnail.jpg b/server/tests/fixtures/custom-thumbnail.jpg
deleted file mode 100644
index ef818442d..000000000
Binary files a/server/tests/fixtures/custom-thumbnail.jpg and /dev/null differ
diff --git a/server/tests/fixtures/custom-thumbnail.png b/server/tests/fixtures/custom-thumbnail.png
deleted file mode 100644
index 9f34daec1..000000000
Binary files a/server/tests/fixtures/custom-thumbnail.png and /dev/null differ
diff --git a/server/tests/fixtures/exif.jpg b/server/tests/fixtures/exif.jpg
deleted file mode 100644
index 2997b38e9..000000000
Binary files a/server/tests/fixtures/exif.jpg and /dev/null differ
diff --git a/server/tests/fixtures/exif.png b/server/tests/fixtures/exif.png
deleted file mode 100644
index a1a0113f8..000000000
Binary files a/server/tests/fixtures/exif.png and /dev/null differ
diff --git a/server/tests/fixtures/live/0-000067.ts b/server/tests/fixtures/live/0-000067.ts
deleted file mode 100644
index a59f41a63..000000000
Binary files a/server/tests/fixtures/live/0-000067.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/0-000068.ts b/server/tests/fixtures/live/0-000068.ts
deleted file mode 100644
index 83dcbbb4c..000000000
Binary files a/server/tests/fixtures/live/0-000068.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/0-000069.ts b/server/tests/fixtures/live/0-000069.ts
deleted file mode 100644
index cafd4e978..000000000
Binary files a/server/tests/fixtures/live/0-000069.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/0-000070.ts b/server/tests/fixtures/live/0-000070.ts
deleted file mode 100644
index 0936199ea..000000000
Binary files a/server/tests/fixtures/live/0-000070.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/0.m3u8 b/server/tests/fixtures/live/0.m3u8
deleted file mode 100644
index c3be19d26..000000000
--- a/server/tests/fixtures/live/0.m3u8
+++ /dev/null
@@ -1,14 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:6
-#EXT-X-TARGETDURATION:2
-#EXT-X-MEDIA-SEQUENCE:68
-#EXT-X-INDEPENDENT-SEGMENTS
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:39.019+0200
-0-000068.ts
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:41.019+0200
-0-000069.ts
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:43.019+0200
-0-000070.
diff --git a/server/tests/fixtures/live/1-000067.ts b/server/tests/fixtures/live/1-000067.ts
deleted file mode 100644
index 17db8f81e..000000000
Binary files a/server/tests/fixtures/live/1-000067.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/1-000068.ts b/server/tests/fixtures/live/1-000068.ts
deleted file mode 100644
index f7bb97040..000000000
Binary files a/server/tests/fixtures/live/1-000068.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/1-000069.ts b/server/tests/fixtures/live/1-000069.ts
deleted file mode 100644
index 64c791337..000000000
Binary files a/server/tests/fixtures/live/1-000069.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/1-000070.ts b/server/tests/fixtures/live/1-000070.ts
deleted file mode 100644
index a5f04f109..000000000
Binary files a/server/tests/fixtures/live/1-000070.ts and /dev/null differ
diff --git a/server/tests/fixtures/live/1.m3u8 b/server/tests/fixtures/live/1.m3u8
deleted file mode 100644
index 26d7fa6b0..000000000
--- a/server/tests/fixtures/live/1.m3u8
+++ /dev/null
@@ -1,14 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:6
-#EXT-X-TARGETDURATION:2
-#EXT-X-MEDIA-SEQUENCE:68
-#EXT-X-INDEPENDENT-SEGMENTS
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:39.019+0200
-1-000068.ts
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:41.019+0200
-1-000069.ts
-#EXTINF:2.000000,
-#EXT-X-PROGRAM-DATE-TIME:2023-04-18T13:38:43.019+0200
-1-000070.ts
diff --git a/server/tests/fixtures/live/master.m3u8 b/server/tests/fixtures/live/master.m3u8
deleted file mode 100644
index 7e52f33cf..000000000
--- a/server/tests/fixtures/live/master.m3u8
+++ /dev/null
@@ -1,8 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:6
-#EXT-X-STREAM-INF:BANDWIDTH=1287342,RESOLUTION=640x360,CODECS="avc1.64001f,mp4a.40.2"
-0.m3u8
-
-#EXT-X-STREAM-INF:BANDWIDTH=3051742,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2"
-1.m3u8
-
diff --git a/server/tests/fixtures/low-bitrate.mp4 b/server/tests/fixtures/low-bitrate.mp4
deleted file mode 100644
index 69004eccc..000000000
Binary files a/server/tests/fixtures/low-bitrate.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/peertube-plugin-test-broken/main.js b/server/tests/fixtures/peertube-plugin-test-broken/main.js
deleted file mode 100644
index afdb6f7a0..000000000
--- a/server/tests/fixtures/peertube-plugin-test-broken/main.js
+++ /dev/null
@@ -1,12 +0,0 @@
-async function register (options) {
- options.unknownFunction()
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-broken/package.json b/server/tests/fixtures/peertube-plugin-test-broken/package.json
deleted file mode 100644
index fd03df216..000000000
--- a/server/tests/fixtures/peertube-plugin-test-broken/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-broken",
- "version": "0.0.1",
- "description": "Plugin test broken",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js b/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
deleted file mode 100644
index 58bc27661..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-one/main.js
+++ /dev/null
@@ -1,85 +0,0 @@
-async function register ({
- registerExternalAuth,
- peertubeHelpers,
- settingsManager,
- unregisterExternalAuth
-}) {
- {
- const result = registerExternalAuth({
- authName: 'external-auth-1',
- authDisplayName: () => 'External Auth 1',
- onLogout: user => peertubeHelpers.logger.info('On logout %s', user.username),
- onAuthRequest: (req, res) => {
- const username = req.query.username
-
- result.userAuthenticated({
- req,
- res,
- username,
- email: username + '@example.com'
- })
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-2',
- authDisplayName: () => 'External Auth 2',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'kefka',
- email: 'kefka@example.com',
- role: 0,
- displayName: 'Kefka Palazzo',
- adminFlags: 1,
- videoQuota: 42000,
- videoQuotaDaily: 42100,
-
- // Always use new value except for videoQuotaDaily field
- userUpdater: ({ fieldName, currentValue, newValue }) => {
- if (fieldName === 'videoQuotaDaily') return currentValue
-
- return newValue
- }
- })
- },
- hookTokenValidity: (options) => {
- if (options.type === 'refresh') {
- return { valid: false }
- }
-
- if (options.type === 'access') {
- const token = options.token
- const now = new Date()
- now.setTime(now.getTime() - 5000)
-
- const createdAt = new Date(token.createdAt)
-
- return { valid: createdAt.getTime() >= now.getTime() }
- }
-
- return { valid: true }
- }
- })
- }
-
- settingsManager.onSettingsChange(settings => {
- if (settings.disableKefka) {
- unregisterExternalAuth('external-auth-2')
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json b/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json
deleted file mode 100644
index 22814b047..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-one/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-external-auth-one",
- "version": "0.0.1",
- "description": "External auth one",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-three/main.js b/server/tests/fixtures/peertube-plugin-test-external-auth-three/main.js
deleted file mode 100644
index 30cedccc6..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-three/main.js
+++ /dev/null
@@ -1,53 +0,0 @@
-async function register ({
- registerExternalAuth,
- peertubeHelpers
-}) {
- {
- const result = registerExternalAuth({
- authName: 'external-auth-7',
- authDisplayName: () => 'External Auth 7',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'cid',
- email: 'cid@example.com',
- displayName: 'Cid Marquez'
- })
- },
- onLogout: (user, req) => {
- return 'https://example.com/redirectUrl'
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-8',
- authDisplayName: () => 'External Auth 8',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'cid',
- email: 'cid@example.com',
- displayName: 'Cid Marquez'
- })
- },
- onLogout: (user, req) => {
- return 'https://example.com/redirectUrl?access_token=' + req.headers['authorization'].split(' ')[1]
- }
- })
- }
-}
-
-async function unregister () {
-
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-three/package.json b/server/tests/fixtures/peertube-plugin-test-external-auth-three/package.json
deleted file mode 100644
index f323d189d..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-three/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-external-auth-three",
- "version": "0.0.1",
- "description": "External auth three",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js b/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js
deleted file mode 100644
index 755dbb62b..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-two/main.js
+++ /dev/null
@@ -1,95 +0,0 @@
-async function register ({
- registerExternalAuth,
- peertubeHelpers
-}) {
- {
- const result = registerExternalAuth({
- authName: 'external-auth-3',
- authDisplayName: () => 'External Auth 3',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'cid',
- email: 'cid@example.com',
- displayName: 'Cid Marquez'
- })
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-4',
- authDisplayName: () => 'External Auth 4',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'kefka2',
- email: 'kefka@example.com',
- displayName: 'Kefka duplication'
- })
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-5',
- authDisplayName: () => 'External Auth 5',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'kefka',
- email: 'kefka@example.com',
- displayName: 'Kefka duplication'
- })
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-6',
- authDisplayName: () => 'External Auth 6',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'existing_user',
- email: 'existing_user@example.com',
- displayName: 'Existing user'
- })
- }
- })
- }
-
- {
- const result = registerExternalAuth({
- authName: 'external-auth-7',
- authDisplayName: () => 'External Auth 7',
- onAuthRequest: (req, res) => {
- result.userAuthenticated({
- req,
- res,
- username: 'existing_user2',
- email: 'custom_email_existing_user2@example.com',
- displayName: 'Existing user 2'
- })
- }
- })
- }
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json b/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json
deleted file mode 100644
index a5ca4d07a..000000000
--- a/server/tests/fixtures/peertube-plugin-test-external-auth-two/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-external-auth-two",
- "version": "0.0.1",
- "description": "External auth two",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json b/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json
deleted file mode 100644
index 52d8313df..000000000
--- a/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Hello world": "Bonjour le monde"
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json b/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json
deleted file mode 100644
index 9e187d83b..000000000
--- a/server/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Hello world": "Ciao, mondo!"
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-filter-translations/main.js b/server/tests/fixtures/peertube-plugin-test-filter-translations/main.js
deleted file mode 100644
index 71c11b2ba..000000000
--- a/server/tests/fixtures/peertube-plugin-test-filter-translations/main.js
+++ /dev/null
@@ -1,21 +0,0 @@
-async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) {
- registerHook({
- target: 'filter:api.videos.list.params',
- handler: obj => addToCount(obj)
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ############################################################################
-
-function addToCount (obj) {
- return Object.assign({}, obj, { count: obj.count + 1 })
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-filter-translations/package.json b/server/tests/fixtures/peertube-plugin-test-filter-translations/package.json
deleted file mode 100644
index 2adce4743..000000000
--- a/server/tests/fixtures/peertube-plugin-test-filter-translations/package.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "peertube-plugin-test-filter-translations",
- "version": "0.0.1",
- "description": "Plugin test filter and translations",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {
- "fr-FR": "./languages/fr.json",
- "it-IT": "./languages/it.json"
- }
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-five/main.js b/server/tests/fixtures/peertube-plugin-test-five/main.js
deleted file mode 100644
index 07dd18654..000000000
--- a/server/tests/fixtures/peertube-plugin-test-five/main.js
+++ /dev/null
@@ -1,23 +0,0 @@
-async function register ({
- getRouter
-}) {
- const router = getRouter()
- router.get('/ping', (req, res) => res.json({ message: 'pong' }))
-
- router.get('/is-authenticated', (req, res) => res.json({ isAuthenticated: res.locals.authenticated }))
-
- router.post('/form/post/mirror', (req, res) => {
- res.json(req.body)
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-five/package.json b/server/tests/fixtures/peertube-plugin-test-five/package.json
deleted file mode 100644
index 1f5d65d9d..000000000
--- a/server/tests/fixtures/peertube-plugin-test-five/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-five",
- "version": "0.0.1",
- "description": "Plugin test 5",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-four/main.js b/server/tests/fixtures/peertube-plugin-test-four/main.js
deleted file mode 100644
index b10177b45..000000000
--- a/server/tests/fixtures/peertube-plugin-test-four/main.js
+++ /dev/null
@@ -1,201 +0,0 @@
-async function register ({
- peertubeHelpers,
- registerHook,
- getRouter
-}) {
- const logger = peertubeHelpers.logger
-
- logger.info('Hello world from plugin four')
-
- {
- const username = 'root'
- const results = await peertubeHelpers.database.query(
- 'SELECT "email" from "user" WHERE "username" = $username',
- {
- type: 'SELECT',
- bind: { username }
- }
- )
-
- logger.info('root email is ' + results[0]['email'])
- }
-
- {
- registerHook({
- target: 'action:api.video.viewed',
- handler: async ({ video }) => {
- const videoFromDB1 = await peertubeHelpers.videos.loadByUrl(video.url)
- const videoFromDB2 = await peertubeHelpers.videos.loadByIdOrUUID(video.id)
- const videoFromDB3 = await peertubeHelpers.videos.loadByIdOrUUID(video.uuid)
-
- if (videoFromDB1.uuid !== videoFromDB2.uuid || videoFromDB2.uuid !== videoFromDB3.uuid) return
-
- logger.info('video from DB uuid is %s.', videoFromDB1.uuid)
-
- await peertubeHelpers.videos.removeVideo(video.id)
-
- logger.info('Video deleted by plugin four.')
- }
- })
- }
-
- {
- const serverActor = await peertubeHelpers.server.getServerActor()
- logger.info('server actor name is %s', serverActor.preferredUsername)
- }
-
- {
- logger.info('server url is %s', peertubeHelpers.config.getWebserverUrl())
- }
-
- {
- const actions = {
- blockServer,
- unblockServer,
- blockAccount,
- unblockAccount,
- blacklist,
- unblacklist
- }
-
- const router = getRouter()
- router.post('/commander', async (req, res) => {
- try {
- await actions[req.body.command](peertubeHelpers, req.body)
-
- res.sendStatus(204)
- } catch (err) {
- logger.error('Error in commander.', { err })
- res.sendStatus(500)
- }
- })
-
- router.get('/server-config', async (req, res) => {
- const serverConfig = await peertubeHelpers.config.getServerConfig()
-
- return res.json({ serverConfig })
- })
-
- router.get('/server-listening-config', async (req, res) => {
- const config = await peertubeHelpers.config.getServerListeningConfig()
-
- return res.json({ config })
- })
-
- router.get('/static-route', async (req, res) => {
- const staticRoute = peertubeHelpers.plugin.getBaseStaticRoute()
-
- return res.json({ staticRoute })
- })
-
- router.get('/router-route', async (req, res) => {
- const routerRoute = peertubeHelpers.plugin.getBaseRouterRoute()
-
- return res.json({ routerRoute })
- })
-
- router.get('/user/:id', async (req, res) => {
- const user = await peertubeHelpers.user.loadById(req.params.id)
- if (!user) return res.status(404).end()
-
- return res.json({
- username: user.username
- })
- })
-
- router.get('/user', async (req, res) => {
- const user = await peertubeHelpers.user.getAuthUser(res)
- if (!user) return res.sendStatus(404)
-
- const isAdmin = user.role === 0
- const isModerator = user.role === 1
- const isUser = user.role === 2
-
- return res.json({
- id: user.id,
- username: user.username,
- displayName: user.Account.name,
- isAdmin,
- isModerator,
- isUser
- })
- })
-
- router.get('/video-files/:id', async (req, res) => {
- const details = await peertubeHelpers.videos.getFiles(req.params.id)
- if (!details) return res.sendStatus(404)
-
- return res.json(details)
- })
-
- router.get('/ffprobe', async (req, res) => {
- const result = await peertubeHelpers.videos.ffprobe(req.query.path)
- if (!result) return res.sendStatus(404)
-
- return res.json(result)
- })
-
- router.post('/send-notification', async (req, res) => {
- peertubeHelpers.socket.sendNotification(req.body.userId, {
- type: 1,
- userId: req.body.userId
- })
-
- return res.sendStatus(201)
- })
-
- router.post('/send-video-live-new-state/:uuid', async (req, res) => {
- const video = await peertubeHelpers.videos.loadByIdOrUUID(req.params.uuid)
- peertubeHelpers.socket.sendVideoLiveNewState(video)
-
- return res.sendStatus(201)
- })
- }
-
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
-
-async function blockServer (peertubeHelpers, body) {
- const serverActor = await peertubeHelpers.server.getServerActor()
-
- await peertubeHelpers.moderation.blockServer({ byAccountId: serverActor.Account.id, hostToBlock: body.hostToBlock })
-}
-
-async function unblockServer (peertubeHelpers, body) {
- const serverActor = await peertubeHelpers.server.getServerActor()
-
- await peertubeHelpers.moderation.unblockServer({ byAccountId: serverActor.Account.id, hostToUnblock: body.hostToUnblock })
-}
-
-async function blockAccount (peertubeHelpers, body) {
- const serverActor = await peertubeHelpers.server.getServerActor()
-
- await peertubeHelpers.moderation.blockAccount({ byAccountId: serverActor.Account.id, handleToBlock: body.handleToBlock })
-}
-
-async function unblockAccount (peertubeHelpers, body) {
- const serverActor = await peertubeHelpers.server.getServerActor()
-
- await peertubeHelpers.moderation.unblockAccount({ byAccountId: serverActor.Account.id, handleToUnblock: body.handleToUnblock })
-}
-
-async function blacklist (peertubeHelpers, body) {
- await peertubeHelpers.moderation.blacklistVideo({
- videoIdOrUUID: body.videoUUID,
- createOptions: body
- })
-}
-
-async function unblacklist (peertubeHelpers, body) {
- await peertubeHelpers.moderation.unblacklistVideo({ videoIdOrUUID: body.videoUUID })
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-four/package.json b/server/tests/fixtures/peertube-plugin-test-four/package.json
deleted file mode 100644
index dda3c7f37..000000000
--- a/server/tests/fixtures/peertube-plugin-test-four/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-four",
- "version": "0.0.1",
- "description": "Plugin test 4",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/main.js b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/main.js
deleted file mode 100644
index f58faa847..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/main.js
+++ /dev/null
@@ -1,69 +0,0 @@
-async function register ({
- registerIdAndPassAuth,
- peertubeHelpers,
- settingsManager,
- unregisterIdAndPassAuth
-}) {
- registerIdAndPassAuth({
- authName: 'spyro-auth',
-
- onLogout: () => {
- peertubeHelpers.logger.info('On logout for auth 1 - 1')
- },
-
- getWeight: () => 15,
-
- login (body) {
- if (body.id === 'spyro' && body.password === 'spyro password') {
- return Promise.resolve({
- username: 'spyro',
- email: 'spyro@example.com',
- role: 2,
- displayName: 'Spyro the Dragon'
- })
- }
-
- return null
- }
- })
-
- registerIdAndPassAuth({
- authName: 'crash-auth',
-
- onLogout: () => {
- peertubeHelpers.logger.info('On logout for auth 1 - 2')
- },
-
- getWeight: () => 50,
-
- login (body) {
- if (body.id === 'crash' && body.password === 'crash password') {
- return Promise.resolve({
- username: 'crash',
- email: 'crash@example.com',
- role: 1,
- displayName: 'Crash Bandicoot'
- })
- }
-
- return null
- }
- })
-
- settingsManager.onSettingsChange(settings => {
- if (settings.disableSpyro) {
- unregisterIdAndPassAuth('spyro-auth')
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json
deleted file mode 100644
index f8ad18a90..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-id-pass-auth-one",
- "version": "0.0.1",
- "description": "Id and pass auth one",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/main.js b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/main.js
deleted file mode 100644
index 1200acfbd..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/main.js
+++ /dev/null
@@ -1,106 +0,0 @@
-async function register ({
- registerIdAndPassAuth,
- peertubeHelpers
-}) {
- registerIdAndPassAuth({
- authName: 'laguna-bad-auth',
-
- onLogout: () => {
- peertubeHelpers.logger.info('On logout for auth 3 - 1')
- },
-
- getWeight: () => 5,
-
- login (body) {
- if (body.id === 'laguna' && body.password === 'laguna password') {
- return Promise.resolve({
- username: 'laguna',
- email: 'laguna@example.com',
- displayName: 'Laguna Loire'
- })
- }
-
- return null
- }
- })
-
- registerIdAndPassAuth({
- authName: 'ward-auth',
-
- getWeight: () => 5,
-
- login (body) {
- if (body.id === 'ward') {
- return Promise.resolve({
- username: '-ward-42',
- email: 'ward@example.com'
- })
- }
-
- return null
- }
- })
-
- registerIdAndPassAuth({
- authName: 'kiros-auth',
-
- getWeight: () => 5,
-
- login (body) {
- if (body.id === 'kiros') {
- return Promise.resolve({
- username: 'kiros',
- email: 'kiros@example.com',
- displayName: 'a'.repeat(5000)
- })
- }
-
- return null
- }
- })
-
- registerIdAndPassAuth({
- authName: 'raine-auth',
-
- getWeight: () => 5,
-
- login (body) {
- if (body.id === 'raine') {
- return Promise.resolve({
- username: 'raine',
- email: 'raine@example.com',
- role: 42
- })
- }
-
- return null
- }
- })
-
- registerIdAndPassAuth({
- authName: 'ellone-auth',
-
- getWeight: () => 5,
-
- login (body) {
- if (body.id === 'ellone') {
- return Promise.resolve({
- username: 'ellone'
- })
- }
-
- return null
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json
deleted file mode 100644
index f9f107b1a..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-id-pass-auth-three",
- "version": "0.0.1",
- "description": "Id and pass auth three",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/main.js b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/main.js
deleted file mode 100644
index fad5abf60..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/main.js
+++ /dev/null
@@ -1,65 +0,0 @@
-async function register ({
- registerIdAndPassAuth,
- peertubeHelpers
-}) {
- registerIdAndPassAuth({
- authName: 'laguna-auth',
-
- onLogout: () => {
- peertubeHelpers.logger.info('On logout for auth 2 - 1')
- },
-
- getWeight: () => 30,
-
- hookTokenValidity: (options) => {
- if (options.type === 'refresh') {
- return { valid: false }
- }
-
- if (options.type === 'access') {
- const token = options.token
- const now = new Date()
- now.setTime(now.getTime() - 5000)
-
- const createdAt = new Date(token.createdAt)
-
- return { valid: createdAt.getTime() >= now.getTime() }
- }
-
- return { valid: true }
- },
-
- login (body) {
- if (body.id === 'laguna' && body.password === 'laguna password') {
- return Promise.resolve({
- username: 'laguna',
- email: 'laguna@example.com',
- displayName: 'Laguna Loire',
- adminFlags: 1,
- videoQuota: 42000,
- videoQuotaDaily: 42100,
-
- // Always use new value except for videoQuotaDaily field
- userUpdater: ({ fieldName, currentValue, newValue }) => {
- if (fieldName === 'videoQuotaDaily') return currentValue
-
- return newValue
- }
- })
- }
-
- return null
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json b/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json
deleted file mode 100644
index 5df15fac1..000000000
--- a/server/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-id-pass-auth-two",
- "version": "0.0.1",
- "description": "Id and pass auth two",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-native/main.js b/server/tests/fixtures/peertube-plugin-test-native/main.js
deleted file mode 100644
index 0390faea9..000000000
--- a/server/tests/fixtures/peertube-plugin-test-native/main.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const print = require('a-native-example')
-
-async function register ({ getRouter }) {
- print('hello world')
-
- const router = getRouter()
-
- router.get('/', (req, res) => {
- print('hello world')
- res.sendStatus(204)
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-native/package.json b/server/tests/fixtures/peertube-plugin-test-native/package.json
deleted file mode 100644
index a6525720b..000000000
--- a/server/tests/fixtures/peertube-plugin-test-native/package.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "peertube-plugin-test-native",
- "version": "0.0.1",
- "description": "Plugin test-native",
- "engine": {
- "peertube": ">=4.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {},
- "dependencies": {
- "a-native-example": "^1.0.0"
- }
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/main.js b/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/main.js
deleted file mode 100644
index ada4a70fe..000000000
--- a/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/main.js
+++ /dev/null
@@ -1,82 +0,0 @@
-async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) {
- registerHook({
- target: 'filter:feed.podcast.rss.create-custom-xmlns.result',
- handler: (result, params) => {
- return result.concat([
- {
- name: "biz",
- value: "https://example.com/biz-xmlns",
- },
- ])
- }
- })
-
- registerHook({
- target: 'filter:feed.podcast.channel.create-custom-tags.result',
- handler: (result, params) => {
- const { videoChannel } = params
- return result.concat([
- {
- name: "fooTag",
- attributes: { "bar": "baz" },
- value: "42",
- },
- {
- name: "biz:videoChannel",
- attributes: { "name": videoChannel.name, "id": videoChannel.id },
- },
- {
- name: "biz:buzzItem",
- value: [
- {
- name: "nestedTag",
- value: "example nested tag",
- },
- ],
- },
- ])
- }
- })
-
- registerHook({
- target: 'filter:feed.podcast.video.create-custom-tags.result',
- handler: (result, params) => {
- const { video, liveItem } = params
- return result.concat([
- {
- name: "fizzTag",
- attributes: { "bar": "baz" },
- value: "21",
- },
- {
- name: "biz:video",
- attributes: { "name": video.name, "id": video.id, "isLive": liveItem },
- },
- {
- name: "biz:buzz",
- value: [
- {
- name: "nestedTag",
- value: "example nested tag",
- },
- ],
- }
- ])
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ############################################################################
-
-function addToCount (obj) {
- return Object.assign({}, obj, { count: obj.count + 1 })
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json b/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json
deleted file mode 100644
index 0f5a05a79..000000000
--- a/server/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "peertube-plugin-test-podcast-custom-tags",
- "version": "0.0.1",
- "description": "Plugin test custom tags in Podcast RSS feeds",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": []
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-six/main.js b/server/tests/fixtures/peertube-plugin-test-six/main.js
deleted file mode 100644
index 243b041e7..000000000
--- a/server/tests/fixtures/peertube-plugin-test-six/main.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const fs = require('fs')
-const path = require('path')
-
-async function register ({
- storageManager,
- peertubeHelpers,
- getRouter
-}) {
- const { logger } = peertubeHelpers
-
- {
- await storageManager.storeData('superkey', { value: 'toto' })
- await storageManager.storeData('anotherkey', { value: 'toto2' })
- await storageManager.storeData('storedArrayKey', ['toto', 'toto2'])
-
- const result = await storageManager.getData('superkey')
- logger.info('superkey stored value is %s', result.value)
-
- const storedArrayValue = await storageManager.getData('storedArrayKey')
- logger.info('storedArrayKey isArray is %s', Array.isArray(storedArrayValue) ? 'true' : 'false')
- logger.info('storedArrayKey stored value is %s', storedArrayValue.join(', '))
- }
-
- {
- getRouter().get('/create-file', async (req, res) => {
- const basePath = peertubeHelpers.plugin.getDataDirectoryPath()
-
- fs.writeFile(path.join(basePath, 'Aladdin.txt'), 'Prince Ali', function (err) {
- if (err) return res.sendStatus(500)
-
- res.sendStatus(200)
- })
- })
- }
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-six/package.json b/server/tests/fixtures/peertube-plugin-test-six/package.json
deleted file mode 100644
index 8c97826b0..000000000
--- a/server/tests/fixtures/peertube-plugin-test-six/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-six",
- "version": "0.0.1",
- "description": "Plugin test 6",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js b/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js
deleted file mode 100644
index c4ae777f5..000000000
--- a/server/tests/fixtures/peertube-plugin-test-transcoding-one/main.js
+++ /dev/null
@@ -1,92 +0,0 @@
-async function register ({ transcodingManager }) {
-
- // Output options
- {
- {
- const builder = () => {
- return {
- outputOptions: [
- '-r 10'
- ]
- }
- }
-
- transcodingManager.addVODProfile('libx264', 'low-vod', builder)
- }
-
- {
- const builder = (options) => {
- return {
- outputOptions: [
- '-r:' + options.streamNum + ' 50'
- ]
- }
- }
-
- transcodingManager.addLiveProfile('libx264', 'high-live', builder)
- }
- }
-
- // Input options
- {
- {
- const builder = () => {
- return {
- inputOptions: [
- '-r 5'
- ]
- }
- }
-
- transcodingManager.addVODProfile('libx264', 'input-options-vod', builder)
- }
-
- {
- const builder = () => {
- return {
- inputOptions: [
- '-r 50'
- ]
- }
- }
-
- transcodingManager.addLiveProfile('libx264', 'input-options-live', builder)
- }
- }
-
- // Scale filters
- {
- {
- const builder = () => {
- return {
- scaleFilter: {
- name: 'Glomgold'
- }
- }
- }
-
- transcodingManager.addVODProfile('libx264', 'bad-scale-vod', builder)
- }
-
- {
- const builder = () => {
- return {
- scaleFilter: {
- name: 'Flintheart'
- }
- }
- }
-
- transcodingManager.addLiveProfile('libx264', 'bad-scale-live', builder)
- }
- }
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-transcoding-one/package.json b/server/tests/fixtures/peertube-plugin-test-transcoding-one/package.json
deleted file mode 100644
index bedbfa051..000000000
--- a/server/tests/fixtures/peertube-plugin-test-transcoding-one/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-transcoding-one",
- "version": "0.0.1",
- "description": "Plugin test transcoding 1",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-transcoding-two/main.js b/server/tests/fixtures/peertube-plugin-test-transcoding-two/main.js
deleted file mode 100644
index a914bce49..000000000
--- a/server/tests/fixtures/peertube-plugin-test-transcoding-two/main.js
+++ /dev/null
@@ -1,38 +0,0 @@
-async function register ({ transcodingManager }) {
-
- {
- const builder = () => {
- return {
- outputOptions: []
- }
- }
-
- transcodingManager.addVODProfile('libopus', 'test-vod-profile', builder)
- transcodingManager.addVODProfile('libvpx-vp9', 'test-vod-profile', builder)
-
- transcodingManager.addVODEncoderPriority('audio', 'libopus', 1000)
- transcodingManager.addVODEncoderPriority('video', 'libvpx-vp9', 1000)
- }
-
- {
- const builder = (options) => {
- return {
- outputOptions: [
- '-b:' + options.streamNum + ' 10K'
- ]
- }
- }
-
- transcodingManager.addLiveProfile('libopus', 'test-live-profile', builder)
- transcodingManager.addLiveEncoderPriority('audio', 'libopus', 1000)
- }
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-transcoding-two/package.json b/server/tests/fixtures/peertube-plugin-test-transcoding-two/package.json
deleted file mode 100644
index 34be0454b..000000000
--- a/server/tests/fixtures/peertube-plugin-test-transcoding-two/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-transcoding-two",
- "version": "0.0.1",
- "description": "Plugin test transcoding 2",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/lib.js b/server/tests/fixtures/peertube-plugin-test-unloading/lib.js
deleted file mode 100644
index f57e7cb01..000000000
--- a/server/tests/fixtures/peertube-plugin-test-unloading/lib.js
+++ /dev/null
@@ -1,2 +0,0 @@
-const d = new Date()
-exports.value = d.getTime()
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/main.js b/server/tests/fixtures/peertube-plugin-test-unloading/main.js
deleted file mode 100644
index 5c8457cef..000000000
--- a/server/tests/fixtures/peertube-plugin-test-unloading/main.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const lib = require('./lib')
-
-async function register ({ getRouter }) {
- const router = getRouter()
- router.get('/get', (req, res) => res.json({ message: lib.value }))
-}
-
-async function unregister () {
-}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-unloading/package.json b/server/tests/fixtures/peertube-plugin-test-unloading/package.json
deleted file mode 100644
index 7076d4b6f..000000000
--- a/server/tests/fixtures/peertube-plugin-test-unloading/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-unloading",
- "version": "0.0.1",
- "description": "Plugin test (modules unloading)",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-video-constants/main.js b/server/tests/fixtures/peertube-plugin-test-video-constants/main.js
deleted file mode 100644
index 06527bd35..000000000
--- a/server/tests/fixtures/peertube-plugin-test-video-constants/main.js
+++ /dev/null
@@ -1,46 +0,0 @@
-async function register ({
- videoCategoryManager,
- videoLicenceManager,
- videoLanguageManager,
- videoPrivacyManager,
- playlistPrivacyManager,
- getRouter
-}) {
- videoLanguageManager.addConstant('al_bhed', 'Al Bhed')
- videoLanguageManager.addLanguage('al_bhed2', 'Al Bhed 2')
- videoLanguageManager.addConstant('al_bhed3', 'Al Bhed 3')
- videoLanguageManager.deleteConstant('en')
- videoLanguageManager.deleteLanguage('fr')
- videoLanguageManager.deleteConstant('al_bhed3')
-
- videoCategoryManager.addCategory(42, 'Best category')
- videoCategoryManager.addConstant(43, 'High best category')
- videoCategoryManager.deleteConstant(1) // Music
- videoCategoryManager.deleteCategory(2) // Films
-
- videoLicenceManager.addLicence(42, 'Best licence')
- videoLicenceManager.addConstant(43, 'High best licence')
- videoLicenceManager.deleteConstant(1) // Attribution
- videoLicenceManager.deleteConstant(7) // Public domain
-
- videoPrivacyManager.deleteConstant(2)
- videoPrivacyManager.deletePrivacy(2)
- playlistPrivacyManager.deleteConstant(3)
- playlistPrivacyManager.deletePlaylistPrivacy(3)
-
- {
- const router = getRouter()
- router.get('/reset-categories', (req, res) => {
- videoCategoryManager.resetConstants()
-
- res.sendStatus(204)
- })
- }
-}
-
-async function unregister () {}
-
-module.exports = {
- register,
- unregister
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-video-constants/package.json b/server/tests/fixtures/peertube-plugin-test-video-constants/package.json
deleted file mode 100644
index 0fcf39933..000000000
--- a/server/tests/fixtures/peertube-plugin-test-video-constants/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-video-constants",
- "version": "0.0.1",
- "description": "Plugin test video constants",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test-websocket/main.js b/server/tests/fixtures/peertube-plugin-test-websocket/main.js
deleted file mode 100644
index 3fde76cfe..000000000
--- a/server/tests/fixtures/peertube-plugin-test-websocket/main.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const WebSocketServer = require('ws').WebSocketServer
-
-async function register ({
- registerWebSocketRoute
-}) {
- const wss = new WebSocketServer({ noServer: true })
-
- wss.on('connection', function connection(ws) {
- ws.on('message', function message(data) {
- if (data.toString() === 'ping') {
- ws.send('pong')
- }
- })
- })
-
- registerWebSocketRoute({
- route: '/toto',
-
- handler: (request, socket, head) => {
- wss.handleUpgrade(request, socket, head, ws => {
- wss.emit('connection', ws, request)
- })
- }
- })
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ###########################################################################
diff --git a/server/tests/fixtures/peertube-plugin-test-websocket/package.json b/server/tests/fixtures/peertube-plugin-test-websocket/package.json
deleted file mode 100644
index 89c8baa04..000000000
--- a/server/tests/fixtures/peertube-plugin-test-websocket/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "peertube-plugin-test-websocket",
- "version": "0.0.1",
- "description": "Plugin test websocket",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {}
-}
diff --git a/server/tests/fixtures/peertube-plugin-test/languages/fr.json b/server/tests/fixtures/peertube-plugin-test/languages/fr.json
deleted file mode 100644
index 9e52f7065..000000000
--- a/server/tests/fixtures/peertube-plugin-test/languages/fr.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Hi": "Coucou"
-}
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js
deleted file mode 100644
index e16bf0ca3..000000000
--- a/server/tests/fixtures/peertube-plugin-test/main.js
+++ /dev/null
@@ -1,477 +0,0 @@
-async function register ({ registerHook, registerSetting, settingsManager, storageManager, peertubeHelpers }) {
- {
- const actionHooks = [
- 'action:application.listening',
- 'action:notifier.notification.created',
-
- 'action:api.video.updated',
- 'action:api.video.deleted',
- 'action:api.video.uploaded',
- 'action:api.video.viewed',
-
- 'action:api.video.file-updated',
-
- 'action:api.video-channel.created',
- 'action:api.video-channel.updated',
- 'action:api.video-channel.deleted',
-
- 'action:api.live-video.created',
- 'action:live.video.state.updated',
-
- 'action:api.video-thread.created',
- 'action:api.video-comment-reply.created',
- 'action:api.video-comment.deleted',
-
- 'action:api.video-caption.created',
- 'action:api.video-caption.deleted',
-
- 'action:api.user.blocked',
- 'action:api.user.unblocked',
- 'action:api.user.registered',
- 'action:api.user.created',
- 'action:api.user.deleted',
- 'action:api.user.updated',
- 'action:api.user.oauth2-got-token',
-
- 'action:api.video-playlist-element.created'
- ]
-
- for (const h of actionHooks) {
- registerHook({
- target: h,
- handler: () => peertubeHelpers.logger.debug('Run hook %s.', h)
- })
- }
-
- for (const h of [ 'action:activity-pub.remote-video.created', 'action:activity-pub.remote-video.updated' ]) {
- registerHook({
- target: h,
- handler: ({ video, videoAPObject }) => {
- peertubeHelpers.logger.debug('Run hook %s - AP %s - video %s.', h, video.name, videoAPObject.name )
- }
- })
- }
- }
-
- registerHook({
- target: 'filter:api.videos.list.params',
- handler: obj => addToCount(obj)
- })
-
- registerHook({
- target: 'filter:api.videos.list.result',
- handler: obj => addToTotal(obj)
- })
-
- registerHook({
- target: 'filter:api.video-playlist.videos.list.params',
- handler: obj => addToCount(obj)
- })
-
- registerHook({
- target: 'filter:api.video-playlist.videos.list.result',
- handler: obj => addToTotal(obj)
- })
-
- registerHook({
- target: 'filter:api.accounts.videos.list.params',
- handler: obj => addToCount(obj)
- })
-
- registerHook({
- target: 'filter:api.accounts.videos.list.result',
- handler: obj => addToTotal(obj, 2)
- })
-
- registerHook({
- target: 'filter:api.video-channels.videos.list.params',
- handler: obj => addToCount(obj, 3)
- })
-
- registerHook({
- target: 'filter:api.video-channels.videos.list.result',
- handler: obj => addToTotal(obj, 3)
- })
-
- registerHook({
- target: 'filter:api.user.me.videos.list.params',
- handler: obj => addToCount(obj, 4)
- })
-
- registerHook({
- target: 'filter:api.user.me.videos.list.result',
- handler: obj => addToTotal(obj, 4)
- })
-
- registerHook({
- target: 'filter:api.user.me.subscription-videos.list.params',
- handler: obj => addToCount(obj)
- })
-
- registerHook({
- target: 'filter:api.user.me.subscription-videos.list.result',
- handler: obj => addToTotal(obj, 4)
- })
-
- registerHook({
- target: 'filter:api.video.get.result',
- handler: video => {
- video.name += ' <3'
-
- return video
- }
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:api.video-channels.list.params',
- handler: obj => addToCount(obj, 1)
- })
-
- registerHook({
- target: 'filter:api.video-channels.list.result',
- handler: obj => addToTotal(obj, 1)
- })
-
- registerHook({
- target: 'filter:api.video-channel.get.result',
- handler: channel => {
- channel.name += ' <3'
-
- return channel
- }
- })
-
- // ---------------------------------------------------------------------------
-
- for (const hook of [ 'filter:api.video.upload.accept.result', 'filter:api.live-video.create.accept.result' ]) {
- registerHook({
- target: hook,
- handler: ({ accepted }, { videoBody, liveVideoBody }) => {
- if (!accepted) return { accepted: false }
-
- const name = videoBody
- ? videoBody.name
- : liveVideoBody.name
-
- if (name.indexOf('bad word') !== -1) return { accepted: false, errorMessage: 'bad word' }
-
- return { accepted: true }
- }
- })
- }
-
- registerHook({
- target: 'filter:api.video.update-file.accept.result',
- handler: ({ accepted }, { videoFile }) => {
- if (!accepted) return { accepted: false }
- if (videoFile.filename.includes('webm')) return { accepted: false, errorMessage: 'no webm' }
-
- return { accepted: true }
- }
- })
-
- registerHook({
- target: 'filter:api.video.pre-import-url.accept.result',
- handler: ({ accepted }, { videoImportBody }) => {
- if (!accepted) return { accepted: false }
- if (videoImportBody.targetUrl.includes('bad')) return { accepted: false, errorMessage: 'bad target url' }
-
- return { accepted: true }
- }
- })
-
- registerHook({
- target: 'filter:api.video.pre-import-torrent.accept.result',
- handler: ({ accepted }, { videoImportBody }) => {
- if (!accepted) return { accepted: false }
- if (videoImportBody.name.includes('bad torrent')) return { accepted: false, errorMessage: 'bad torrent' }
-
- return { accepted: true }
- }
- })
-
- registerHook({
- target: 'filter:api.video.post-import-url.accept.result',
- handler: ({ accepted }, { video }) => {
- if (!accepted) return { accepted: false }
- if (video.name.includes('bad word')) return { accepted: false, errorMessage: 'bad word' }
-
- return { accepted: true }
- }
- })
-
- registerHook({
- target: 'filter:api.video.post-import-torrent.accept.result',
- handler: ({ accepted }, { video }) => {
- if (!accepted) return { accepted: false }
- if (video.name.includes('bad word')) return { accepted: false, errorMessage: 'bad word' }
-
- return { accepted: true }
- }
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:api.video-thread.create.accept.result',
- handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody)
- })
-
- registerHook({
- target: 'filter:api.video-comment-reply.create.accept.result',
- handler: ({ accepted }, { commentBody }) => checkCommentBadWord(accepted, commentBody)
- })
-
- registerHook({
- target: 'filter:activity-pub.remote-video-comment.create.accept.result',
- handler: ({ accepted }, { comment }) => checkCommentBadWord(accepted, comment)
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:activity-pub.activity.context.build.result',
- handler: context => context.concat([ { recordedAt: 'https://schema.org/recordedAt' } ])
- })
-
- registerHook({
- target: 'filter:activity-pub.video.json-ld.build.result',
- handler: (jsonld, { video }) => ({ ...jsonld, videoName: video.name })
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:api.video-threads.list.params',
- handler: obj => addToCount(obj)
- })
-
- registerHook({
- target: 'filter:api.video-threads.list.result',
- handler: obj => addToTotal(obj)
- })
-
- registerHook({
- target: 'filter:api.video-thread-comments.list.result',
- handler: obj => {
- obj.data.forEach(c => c.text += ' <3')
-
- return obj
- }
- })
-
- registerHook({
- target: 'filter:video.auto-blacklist.result',
- handler: (blacklisted, { video }) => {
- if (blacklisted) return true
- if (video.name.includes('please blacklist me')) return true
-
- return false
- }
- })
-
- {
- registerHook({
- target: 'filter:api.user.signup.allowed.result',
- handler: (result, params) => {
- if (params && params.body && params.body.email && params.body.email.includes('jma 1')) {
- return { allowed: false, errorMessage: 'No jma 1' }
- }
-
- return result
- }
- })
-
- registerHook({
- target: 'filter:api.user.request-signup.allowed.result',
- handler: (result, params) => {
- if (params && params.body && params.body.email && params.body.email.includes('jma 2')) {
- return { allowed: false, errorMessage: 'No jma 2' }
- }
-
- return result
- }
- })
- }
-
- registerHook({
- target: 'filter:api.download.torrent.allowed.result',
- handler: (result, params) => {
- if (params && params.downloadName.includes('bad torrent')) {
- return { allowed: false, errorMessage: 'Liu Bei' }
- }
-
- return result
- }
- })
-
- registerHook({
- target: 'filter:api.download.video.allowed.result',
- handler: async (result, params) => {
- const loggedInUser = await peertubeHelpers.user.getAuthUser(params.res)
- if (loggedInUser) return { allowed: true }
-
- if (params && !params.streamingPlaylist && params.video.name.includes('bad file')) {
- return { allowed: false, errorMessage: 'Cao Cao' }
- }
-
- if (params && params.streamingPlaylist && params.video.name.includes('bad playlist file')) {
- return { allowed: false, errorMessage: 'Sun Jian' }
- }
-
- return result
- }
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:html.embed.video.allowed.result',
- handler: (result, params) => {
- return {
- allowed: false,
- html: 'Lu Bu'
- }
- }
- })
-
- registerHook({
- target: 'filter:html.embed.video-playlist.allowed.result',
- handler: (result, params) => {
- return {
- allowed: false,
- html: 'Diao Chan'
- }
- }
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:html.client.json-ld.result',
- handler: (jsonld, context) => {
- if (!context || !context.video) return jsonld
-
- return Object.assign(jsonld, { recordedAt: 'http://example.com/recordedAt' })
- }
- })
-
- // ---------------------------------------------------------------------------
-
- registerHook({
- target: 'filter:api.server.stats.get.result',
- handler: (result) => {
- return { ...result, customStats: 14 }
- }
- })
-
- registerHook({
- target: 'filter:job-queue.process.params',
- handler: (object, context) => {
- if (context.type !== 'video-studio-edition') return object
-
- object.data.tasks = [
- {
- name: 'cut',
- options: {
- start: 0,
- end: 1
- }
- }
- ]
-
- return object
- }
- })
-
- registerHook({
- target: 'filter:transcoding.auto.resolutions-to-transcode.result',
- handler: (object, context) => {
- if (context.video.name.includes('transcode-filter')) {
- object = [ 100 ]
- }
-
- return object
- }
- })
-
- // Upload/import/live attributes
- for (const target of [
- 'filter:api.video.upload.video-attribute.result',
- 'filter:api.video.import-url.video-attribute.result',
- 'filter:api.video.import-torrent.video-attribute.result',
- 'filter:api.video.live.video-attribute.result'
- ]) {
- registerHook({
- target,
- handler: (result) => {
- return { ...result, description: result.description + ' - ' + target }
- }
- })
- }
-
- {
- const filterHooks = [
- 'filter:api.search.videos.local.list.params',
- 'filter:api.search.videos.local.list.result',
- 'filter:api.search.videos.index.list.params',
- 'filter:api.search.videos.index.list.result',
- 'filter:api.search.video-channels.local.list.params',
- 'filter:api.search.video-channels.local.list.result',
- 'filter:api.search.video-channels.index.list.params',
- 'filter:api.search.video-channels.index.list.result',
- 'filter:api.search.video-playlists.local.list.params',
- 'filter:api.search.video-playlists.local.list.result',
- 'filter:api.search.video-playlists.index.list.params',
- 'filter:api.search.video-playlists.index.list.result',
-
- 'filter:api.overviews.videos.list.params',
- 'filter:api.overviews.videos.list.result',
-
- 'filter:job-queue.process.params',
- 'filter:job-queue.process.result'
- ]
-
- for (const h of filterHooks) {
- registerHook({
- target: h,
- handler: (obj) => {
- peertubeHelpers.logger.debug('Run hook %s.', h)
-
- return obj
- }
- })
- }
- }
-}
-
-async function unregister () {
- return
-}
-
-module.exports = {
- register,
- unregister
-}
-
-// ############################################################################
-
-function addToCount (obj, amount = 1) {
- return Object.assign({}, obj, { count: obj.count + amount })
-}
-
-function addToTotal (result, amount = 1) {
- return {
- data: result.data,
- total: result.total + amount
- }
-}
-
-function checkCommentBadWord (accepted, commentBody) {
- if (!accepted) return { accepted: false }
- if (commentBody.text.indexOf('bad word') !== -1) return { accepted: false, errorMessage: 'bad word '}
-
- return { accepted: true }
-}
diff --git a/server/tests/fixtures/peertube-plugin-test/package.json b/server/tests/fixtures/peertube-plugin-test/package.json
deleted file mode 100644
index 108f21fd6..000000000
--- a/server/tests/fixtures/peertube-plugin-test/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "peertube-plugin-test",
- "version": "0.0.1",
- "description": "Plugin test",
- "engine": {
- "peertube": ">=1.3.0"
- },
- "keywords": [
- "peertube",
- "plugin"
- ],
- "homepage": "https://github.com/Chocobozzz/PeerTube",
- "author": "Chocobozzz",
- "bugs": "https://github.com/Chocobozzz/PeerTube/issues",
- "library": "./main.js",
- "staticDirs": {},
- "css": [],
- "clientScripts": [],
- "translations": {
- "fr-FR": "./languages/fr.json"
- }
-}
diff --git a/server/tests/fixtures/rtmps.cert b/server/tests/fixtures/rtmps.cert
deleted file mode 100644
index 3ef606c52..000000000
--- a/server/tests/fixtures/rtmps.cert
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDazCCAlOgAwIBAgIUKNycLAZUs2jFsWUW+zZhBkpLB2wwDQYJKoZIhvcNAQEL
-BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
-GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTExMDUxMDA4MzhaFw0yMTEy
-MDUxMDA4MzhaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
-HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQDak20d81KG/9mVLU6Qw/uRniC935yf9Rlp8FVCDxUd
-zLbfHjrnIOv8kqinUI0nuEQC4DnF7Rbafe88WDU33Q8ixU/R0czUGq1AEwIjyN30
-5NjokCb26xWIly7RCfc/Ot6tjguHwKvcxqJMNC0Lit9Go9MDVnGFLkgHia68P72T
-ZDVV44YpzwYDicwQs5C4nZ4yzAeclia07qfUY0VAEZlxJ/9zjwYHCT0AKaEPH35E
-dUvjuvJ1OSHSN1S4acR+TPR3FwKQh3H/M/GWIqoiIOpdjFUBLs80QOM2aNrLmlyP
-JtyFJLxCP7Ery9fGY/yzHeSxpgOKwZopD6uHZKi5yazNAgMBAAGjUzBRMB0GA1Ud
-DgQWBBSSjhRQdWsybNQMLMhkwV+xiP2uoDAfBgNVHSMEGDAWgBSSjhRQdWsybNQM
-LMhkwV+xiP2uoDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQC8
-rJu3J5sqVKNQaXOmLPd49RM7KG3Y1KPqbQi1lh+sW6aefZ9daeh3JDYGBZGPG/Fi
-IMMP+LhGG0WqDm4ClK00wyNhBuNPEyzvuN/WMRX5djPxO1IZi+KogFwXsn853Ov9
-oV3nxArNNjDu2n92FiB7RTlXRXPIoRo2zEBcLvveGySn9XUazRzlqx6FAxYe2xsw
-U3cZ6/wwU1YsEZa5bwIQk+gkFj3zDsTyEkn2ntcE2NlR+AhCHKa/yAxgPFycAVPX
-2o+wNnc6H4syP98mMGj9hEE3RSJyCPgGBlgi7Swl64G3YygFPJzfLX9YTuxwr/eI
-oitEjF9ljtmdEnf0RdOj
------END CERTIFICATE-----
diff --git a/server/tests/fixtures/rtmps.key b/server/tests/fixtures/rtmps.key
deleted file mode 100644
index 14a85e70a..000000000
--- a/server/tests/fixtures/rtmps.key
+++ /dev/null
@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDak20d81KG/9mV
-LU6Qw/uRniC935yf9Rlp8FVCDxUdzLbfHjrnIOv8kqinUI0nuEQC4DnF7Rbafe88
-WDU33Q8ixU/R0czUGq1AEwIjyN305NjokCb26xWIly7RCfc/Ot6tjguHwKvcxqJM
-NC0Lit9Go9MDVnGFLkgHia68P72TZDVV44YpzwYDicwQs5C4nZ4yzAeclia07qfU
-Y0VAEZlxJ/9zjwYHCT0AKaEPH35EdUvjuvJ1OSHSN1S4acR+TPR3FwKQh3H/M/GW
-IqoiIOpdjFUBLs80QOM2aNrLmlyPJtyFJLxCP7Ery9fGY/yzHeSxpgOKwZopD6uH
-ZKi5yazNAgMBAAECggEAND7C+UK8+jnTl13CBsZhrnfemaQGexGJ5pGkv2p9gKb7
-Gy/Nooty/OdNWtjdNJ5N22YfSRkXulgZxBHNfrHfOU9yedOtIxHRUZx5iXYs36mH
-02cJeUHN3t1MOnkoWTvIGDH4vZUnP1lXV+Gs1rJ2Fht4h7a04cGjQ/H8C1EtDjqX
-kzH2T/gwo5hdGrxifRTs5wCVoP/iUwNtBI4WrY2rfC6sV+NOICgp0xX0NvGWZ8UT
-K1Ntpl8IxnxmeBd26d+Gbjc9d9fIRDtyXby4YOIlDZxnIiZEI0I452JqGl/jrXaP
-F3Troet4OBj5uH5s374d6ubKq66XogiLMIjEj2tYfQKBgQDtuaOu+y549bFJKVc9
-TCiWSOl/0j2kKKG8UG23zMC//AT13WqZDT5ObfOAuMhy70au/PD84D9RU/+gRVWb
-ptfybD9ugRNC8PkmdT82uYtZpS4+Xw4qyWVRgqQFmjSYz63cLcULVi8kiG8XmG5u
-QGgT/tNv5mxhOMUGSxhClOpLBwKBgQDrYO9UrLs+gDVKbHF4Dh+YJpaLnwwF+TFA
-j3ZbkE0XEeeXp/YDgyClmWwEkteJeNljtreCZ9gMkx3JdR9i8uecUQ2tFDBg3cN0
-BZAex2jFwSb0QbfzHNnE07I+aEIfHHjYXjzABl+1Yt95giKjce0Ke+8Zzahue0+9
-lYcAHemQiwKBgQCs9JAbIdJo3NBUW0iGZ19sH7YKciq4wXsSaC27OLPPugrd2m7Q
-1arMIwCzWT01KdLyQ0MNqBVJFWT49RjYuuWIEauAuVYLMQkEKu+H4Cx7V0syw7Op
-+4bEa9jr3op/1zE17PLcUaLQ4JZ6w0Ms4Z0XVyH72thlT4lBD+ehoXhohwKBgEtJ
-LAPnY9Sv6Vuup/SAf/aIkSqDarMWa3x85pyO4Tl5zpuha3zgGjcdhYFI/ovIDbBp
-JvUdBeuvup1PSwS5MP+8pSUxCfBRvkyD4v8VRRvLlgwWYSHvnm/oTmDLtCqDTtvV
-+JRq9X3s7BHPYAjrTahGz8lvEGqWIoE/LHkLGEPVAoGAaF3VHuqDfmD9PJUAlsU1
-qxN7yfOd2ve0+66Ghus24DVqUFqwp5f2AxZXYUtSaNUp8fVbqIi+Yq3YDTU2KfId
-5QNA/AiKi4VUNLElsG5DZlbszsE5KNp9fWQoggdQ5LND7AGEKeFERHOVQ7C5sc/C
-omIqK5/PsZmaf4OZLyecxJY=
------END PRIVATE KEY-----
diff --git a/server/tests/fixtures/sample.ogg b/server/tests/fixtures/sample.ogg
deleted file mode 100644
index 0d7f43eb7..000000000
Binary files a/server/tests/fixtures/sample.ogg and /dev/null differ
diff --git a/server/tests/fixtures/subtitle-bad.txt b/server/tests/fixtures/subtitle-bad.txt
deleted file mode 100644
index a2a30ae47..000000000
--- a/server/tests/fixtures/subtitle-bad.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-1
-00:00:01,600 --> 00:00:04,200
-English (US)
-
-2
-00:00:05,900 --> 00:00:07,999
-This is a subtitle in American English
-
-3
-00:00:10,000 --> 00:00:14,000
-Adding subtitles is very easy to do
\ No newline at end of file
diff --git a/server/tests/fixtures/subtitle-good.srt b/server/tests/fixtures/subtitle-good.srt
deleted file mode 100644
index a2a30ae47..000000000
--- a/server/tests/fixtures/subtitle-good.srt
+++ /dev/null
@@ -1,11 +0,0 @@
-1
-00:00:01,600 --> 00:00:04,200
-English (US)
-
-2
-00:00:05,900 --> 00:00:07,999
-This is a subtitle in American English
-
-3
-00:00:10,000 --> 00:00:14,000
-Adding subtitles is very easy to do
\ No newline at end of file
diff --git a/server/tests/fixtures/subtitle-good1.vtt b/server/tests/fixtures/subtitle-good1.vtt
deleted file mode 100644
index 04cd23946..000000000
--- a/server/tests/fixtures/subtitle-good1.vtt
+++ /dev/null
@@ -1,8 +0,0 @@
-WEBVTT
-
-00:01.000 --> 00:04.000
-Subtitle good 1.
-
-00:05.000 --> 00:09.000
-- It will perforate your stomach.
-- You could die.
\ No newline at end of file
diff --git a/server/tests/fixtures/subtitle-good2.vtt b/server/tests/fixtures/subtitle-good2.vtt
deleted file mode 100644
index 4d3256def..000000000
--- a/server/tests/fixtures/subtitle-good2.vtt
+++ /dev/null
@@ -1,8 +0,0 @@
-WEBVTT
-
-00:01.000 --> 00:04.000
-Subtitle good 2.
-
-00:05.000 --> 00:09.000
-- It will perforate your stomach.
-- You could die.
\ No newline at end of file
diff --git a/server/tests/fixtures/thumbnail-playlist.jpg b/server/tests/fixtures/thumbnail-playlist.jpg
deleted file mode 100644
index 12de5817b..000000000
Binary files a/server/tests/fixtures/thumbnail-playlist.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video-720p.torrent b/server/tests/fixtures/video-720p.torrent
deleted file mode 100644
index 64bfd5220..000000000
Binary files a/server/tests/fixtures/video-720p.torrent and /dev/null differ
diff --git a/server/tests/fixtures/video_import_preview.jpg b/server/tests/fixtures/video_import_preview.jpg
deleted file mode 100644
index a98da178f..000000000
Binary files a/server/tests/fixtures/video_import_preview.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_import_preview_yt_dlp.jpg b/server/tests/fixtures/video_import_preview_yt_dlp.jpg
deleted file mode 100644
index 9e8833bf9..000000000
Binary files a/server/tests/fixtures/video_import_preview_yt_dlp.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_import_thumbnail.jpg b/server/tests/fixtures/video_import_thumbnail.jpg
deleted file mode 100644
index 9ee1bc382..000000000
Binary files a/server/tests/fixtures/video_import_thumbnail.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_import_thumbnail_yt_dlp.jpg b/server/tests/fixtures/video_import_thumbnail_yt_dlp.jpg
deleted file mode 100644
index a10e07207..000000000
Binary files a/server/tests/fixtures/video_import_thumbnail_yt_dlp.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short.avi b/server/tests/fixtures/video_short.avi
deleted file mode 100644
index 88979cab2..000000000
Binary files a/server/tests/fixtures/video_short.avi and /dev/null differ
diff --git a/server/tests/fixtures/video_short.mkv b/server/tests/fixtures/video_short.mkv
deleted file mode 100644
index a67f4f806..000000000
Binary files a/server/tests/fixtures/video_short.mkv and /dev/null differ
diff --git a/server/tests/fixtures/video_short.mp4 b/server/tests/fixtures/video_short.mp4
deleted file mode 100644
index 35678362b..000000000
Binary files a/server/tests/fixtures/video_short.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short.mp4.jpg b/server/tests/fixtures/video_short.mp4.jpg
deleted file mode 100644
index 7ac29122c..000000000
Binary files a/server/tests/fixtures/video_short.mp4.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short.ogv b/server/tests/fixtures/video_short.ogv
deleted file mode 100644
index 9e253da82..000000000
Binary files a/server/tests/fixtures/video_short.ogv and /dev/null differ
diff --git a/server/tests/fixtures/video_short.ogv.jpg b/server/tests/fixtures/video_short.ogv.jpg
deleted file mode 100644
index 5bc63969b..000000000
Binary files a/server/tests/fixtures/video_short.ogv.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short.webm b/server/tests/fixtures/video_short.webm
deleted file mode 100644
index bf4b0ab6c..000000000
Binary files a/server/tests/fixtures/video_short.webm and /dev/null differ
diff --git a/server/tests/fixtures/video_short.webm.jpg b/server/tests/fixtures/video_short.webm.jpg
deleted file mode 100644
index 7ac29122c..000000000
Binary files a/server/tests/fixtures/video_short.webm.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short1-preview.webm.jpg b/server/tests/fixtures/video_short1-preview.webm.jpg
deleted file mode 100644
index 15454942d..000000000
Binary files a/server/tests/fixtures/video_short1-preview.webm.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short1.webm b/server/tests/fixtures/video_short1.webm
deleted file mode 100644
index 70ac0c644..000000000
Binary files a/server/tests/fixtures/video_short1.webm and /dev/null differ
diff --git a/server/tests/fixtures/video_short1.webm.jpg b/server/tests/fixtures/video_short1.webm.jpg
deleted file mode 100644
index b2740d73d..000000000
Binary files a/server/tests/fixtures/video_short1.webm.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short2.webm b/server/tests/fixtures/video_short2.webm
deleted file mode 100644
index 13d72dff7..000000000
Binary files a/server/tests/fixtures/video_short2.webm and /dev/null differ
diff --git a/server/tests/fixtures/video_short2.webm.jpg b/server/tests/fixtures/video_short2.webm.jpg
deleted file mode 100644
index afe476c7f..000000000
Binary files a/server/tests/fixtures/video_short2.webm.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short3.webm b/server/tests/fixtures/video_short3.webm
deleted file mode 100644
index cde5dcd58..000000000
Binary files a/server/tests/fixtures/video_short3.webm and /dev/null differ
diff --git a/server/tests/fixtures/video_short3.webm.jpg b/server/tests/fixtures/video_short3.webm.jpg
deleted file mode 100644
index b572f676e..000000000
Binary files a/server/tests/fixtures/video_short3.webm.jpg and /dev/null differ
diff --git a/server/tests/fixtures/video_short_0p.mp4 b/server/tests/fixtures/video_short_0p.mp4
deleted file mode 100644
index 2069a49b8..000000000
Binary files a/server/tests/fixtures/video_short_0p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_144p.m3u8 b/server/tests/fixtures/video_short_144p.m3u8
deleted file mode 100644
index 96568625b..000000000
--- a/server/tests/fixtures/video_short_144p.m3u8
+++ /dev/null
@@ -1,13 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:7
-#EXT-X-TARGETDURATION:4
-#EXT-X-MEDIA-SEQUENCE:0
-#EXT-X-PLAYLIST-TYPE:VOD
-#EXT-X-MAP:URI="3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4",BYTERANGE="1375@0"
-#EXTINF:4.000000,
-#EXT-X-BYTERANGE:10518@1375
-3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4
-#EXTINF:1.000000,
-#EXT-X-BYTERANGE:3741@11893
-3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4
-#EXT-X-ENDLIST
diff --git a/server/tests/fixtures/video_short_144p.mp4 b/server/tests/fixtures/video_short_144p.mp4
deleted file mode 100644
index 047d43c17..000000000
Binary files a/server/tests/fixtures/video_short_144p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_240p.m3u8 b/server/tests/fixtures/video_short_240p.m3u8
deleted file mode 100644
index 96568625b..000000000
--- a/server/tests/fixtures/video_short_240p.m3u8
+++ /dev/null
@@ -1,13 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:7
-#EXT-X-TARGETDURATION:4
-#EXT-X-MEDIA-SEQUENCE:0
-#EXT-X-PLAYLIST-TYPE:VOD
-#EXT-X-MAP:URI="3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4",BYTERANGE="1375@0"
-#EXTINF:4.000000,
-#EXT-X-BYTERANGE:10518@1375
-3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4
-#EXTINF:1.000000,
-#EXT-X-BYTERANGE:3741@11893
-3dd13e27-1ae1-441c-9b77-48c6b95603be-144-fragmented.mp4
-#EXT-X-ENDLIST
diff --git a/server/tests/fixtures/video_short_240p.mp4 b/server/tests/fixtures/video_short_240p.mp4
deleted file mode 100644
index 46609e81a..000000000
Binary files a/server/tests/fixtures/video_short_240p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_360p.m3u8 b/server/tests/fixtures/video_short_360p.m3u8
deleted file mode 100644
index f7072dc6d..000000000
--- a/server/tests/fixtures/video_short_360p.m3u8
+++ /dev/null
@@ -1,13 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:7
-#EXT-X-TARGETDURATION:4
-#EXT-X-MEDIA-SEQUENCE:0
-#EXT-X-PLAYLIST-TYPE:VOD
-#EXT-X-MAP:URI="05c40acd-3e94-4d25-ade8-97f7ff2cf0ac-360-fragmented.mp4",BYTERANGE="1376@0"
-#EXTINF:4.000000,
-#EXT-X-BYTERANGE:19987@1376
-05c40acd-3e94-4d25-ade8-97f7ff2cf0ac-360-fragmented.mp4
-#EXTINF:1.000000,
-#EXT-X-BYTERANGE:9147@21363
-05c40acd-3e94-4d25-ade8-97f7ff2cf0ac-360-fragmented.mp4
-#EXT-X-ENDLIST
diff --git a/server/tests/fixtures/video_short_360p.mp4 b/server/tests/fixtures/video_short_360p.mp4
deleted file mode 100644
index 7a8189bbc..000000000
Binary files a/server/tests/fixtures/video_short_360p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_480.webm b/server/tests/fixtures/video_short_480.webm
deleted file mode 100644
index 3145105e1..000000000
Binary files a/server/tests/fixtures/video_short_480.webm and /dev/null differ
diff --git a/server/tests/fixtures/video_short_480p.m3u8 b/server/tests/fixtures/video_short_480p.m3u8
deleted file mode 100644
index 5ff30dfa7..000000000
--- a/server/tests/fixtures/video_short_480p.m3u8
+++ /dev/null
@@ -1,13 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:7
-#EXT-X-TARGETDURATION:4
-#EXT-X-MEDIA-SEQUENCE:0
-#EXT-X-PLAYLIST-TYPE:VOD
-#EXT-X-MAP:URI="f9377e69-d8f2-4de8-8087-ddbca6629829-480-fragmented.mp4",BYTERANGE="1376@0"
-#EXTINF:4.000000,
-#EXT-X-BYTERANGE:26042@1376
-f9377e69-d8f2-4de8-8087-ddbca6629829-480-fragmented.mp4
-#EXTINF:1.000000,
-#EXT-X-BYTERANGE:12353@27418
-f9377e69-d8f2-4de8-8087-ddbca6629829-480-fragmented.mp4
-#EXT-X-ENDLIST
diff --git a/server/tests/fixtures/video_short_480p.mp4 b/server/tests/fixtures/video_short_480p.mp4
deleted file mode 100644
index e05b58b6b..000000000
Binary files a/server/tests/fixtures/video_short_480p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_4k.mp4 b/server/tests/fixtures/video_short_4k.mp4
deleted file mode 100644
index 402479743..000000000
Binary files a/server/tests/fixtures/video_short_4k.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_720p.m3u8 b/server/tests/fixtures/video_short_720p.m3u8
deleted file mode 100644
index 7cee94032..000000000
--- a/server/tests/fixtures/video_short_720p.m3u8
+++ /dev/null
@@ -1,13 +0,0 @@
-#EXTM3U
-#EXT-X-VERSION:7
-#EXT-X-TARGETDURATION:4
-#EXT-X-MEDIA-SEQUENCE:0
-#EXT-X-PLAYLIST-TYPE:VOD
-#EXT-X-MAP:URI="c1014aa4-d1f4-4b66-927b-c23d283fcae0-720-fragmented.mp4",BYTERANGE="1356@0"
-#EXTINF:4.000000,
-#EXT-X-BYTERANGE:39260@1356
-c1014aa4-d1f4-4b66-927b-c23d283fcae0-720-fragmented.mp4
-#EXTINF:1.000000,
-#EXT-X-BYTERANGE:18493@40616
-c1014aa4-d1f4-4b66-927b-c23d283fcae0-720-fragmented.mp4
-#EXT-X-ENDLIST
diff --git a/server/tests/fixtures/video_short_720p.mp4 b/server/tests/fixtures/video_short_720p.mp4
deleted file mode 100644
index 35e8f69a7..000000000
Binary files a/server/tests/fixtures/video_short_720p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_fake.webm b/server/tests/fixtures/video_short_fake.webm
deleted file mode 100644
index d85290ae5..000000000
--- a/server/tests/fixtures/video_short_fake.webm
+++ /dev/null
@@ -1 +0,0 @@
-this is a fake video mouahahah
diff --git a/server/tests/fixtures/video_short_mp3_256k.mp4 b/server/tests/fixtures/video_short_mp3_256k.mp4
deleted file mode 100644
index 4c1c7b45e..000000000
Binary files a/server/tests/fixtures/video_short_mp3_256k.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_short_no_audio.mp4 b/server/tests/fixtures/video_short_no_audio.mp4
deleted file mode 100644
index 329d20fba..000000000
Binary files a/server/tests/fixtures/video_short_no_audio.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_very_long_10p.mp4 b/server/tests/fixtures/video_very_long_10p.mp4
deleted file mode 100644
index 852297933..000000000
Binary files a/server/tests/fixtures/video_very_long_10p.mp4 and /dev/null differ
diff --git a/server/tests/fixtures/video_very_short_240p.mp4 b/server/tests/fixtures/video_very_short_240p.mp4
deleted file mode 100644
index 95b6be92a..000000000
Binary files a/server/tests/fixtures/video_very_short_240p.mp4 and /dev/null differ
diff --git a/server/tests/helpers/comment-model.ts b/server/tests/helpers/comment-model.ts
deleted file mode 100644
index e39cae442..000000000
--- a/server/tests/helpers/comment-model.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { VideoCommentModel } from '../../models/video/video-comment'
-
-class CommentMock {
- text: string
-
- extractMentions = VideoCommentModel.prototype.extractMentions
-
- isOwned = () => true
-}
-
-describe('Comment model', function () {
- it('Should correctly extract mentions', async function () {
- const comment = new CommentMock()
-
- comment.text = '@florian @jean@localhost:9000 @flo @another@localhost:9000 @flo2@jean.com hello ' +
- 'email@localhost:9000 coucou.com no? @chocobozzz @chocobozzz @end'
- const result = comment.extractMentions().sort((a, b) => a.localeCompare(b))
-
- expect(result).to.deep.equal([ 'another', 'chocobozzz', 'end', 'flo', 'florian', 'jean' ])
- })
-})
diff --git a/server/tests/helpers/core-utils.ts b/server/tests/helpers/core-utils.ts
deleted file mode 100644
index cd2f07e4a..000000000
--- a/server/tests/helpers/core-utils.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { snakeCase } from 'lodash'
-import validator from 'validator'
-import { getAverageTheoreticalBitrate, getMaxTheoreticalBitrate } from '@shared/core-utils'
-import { VideoResolution } from '@shared/models'
-import { objectConverter, parseBytes, parseDurationToMs } from '../../helpers/core-utils'
-
-describe('Parse Bytes', function () {
-
- it('Should pass on valid value', async function () {
- // just return it
- expect(parseBytes(-1024)).to.equal(-1024)
- expect(parseBytes(1024)).to.equal(1024)
- expect(parseBytes(1048576)).to.equal(1048576)
- expect(parseBytes('1024')).to.equal(1024)
- expect(parseBytes('1048576')).to.equal(1048576)
-
- // sizes
- expect(parseBytes('1B')).to.equal(1024)
- expect(parseBytes('1MB')).to.equal(1048576)
- expect(parseBytes('1GB')).to.equal(1073741824)
- expect(parseBytes('1TB')).to.equal(1099511627776)
-
- expect(parseBytes('5GB')).to.equal(5368709120)
- expect(parseBytes('5TB')).to.equal(5497558138880)
-
- expect(parseBytes('1024B')).to.equal(1048576)
- expect(parseBytes('1024MB')).to.equal(1073741824)
- expect(parseBytes('1024GB')).to.equal(1099511627776)
- expect(parseBytes('1024TB')).to.equal(1125899906842624)
-
- // with whitespace
- expect(parseBytes('1 GB')).to.equal(1073741824)
- expect(parseBytes('1\tGB')).to.equal(1073741824)
-
- // sum value
- expect(parseBytes('1TB 1024MB')).to.equal(1100585369600)
- expect(parseBytes('4GB 1024MB')).to.equal(5368709120)
- expect(parseBytes('4TB 1024GB')).to.equal(5497558138880)
- expect(parseBytes('4TB 1024GB 0MB')).to.equal(5497558138880)
- expect(parseBytes('1024TB 1024GB 1024MB')).to.equal(1127000492212224)
- })
-
- it('Should be invalid when given invalid value', async function () {
- expect(parseBytes('6GB 1GB')).to.equal(6)
- })
-})
-
-describe('Parse duration', function () {
-
- it('Should pass when given valid value', async function () {
- expect(parseDurationToMs(35)).to.equal(35)
- expect(parseDurationToMs(-35)).to.equal(-35)
- expect(parseDurationToMs('35 seconds')).to.equal(35 * 1000)
- expect(parseDurationToMs('1 minute')).to.equal(60 * 1000)
- expect(parseDurationToMs('1 hour')).to.equal(3600 * 1000)
- expect(parseDurationToMs('35 hours')).to.equal(3600 * 35 * 1000)
- })
-
- it('Should be invalid when given invalid value', async function () {
- expect(parseBytes('35m 5s')).to.equal(35)
- })
-})
-
-describe('Object', function () {
-
- it('Should convert an object', async function () {
- function keyConverter (k: string) {
- return snakeCase(k)
- }
-
- function valueConverter (v: any) {
- if (validator.isNumeric(v + '')) return parseInt('' + v, 10)
-
- return v
- }
-
- const obj = {
- mySuperKey: 'hello',
- mySuper2Key: '45',
- mySuper3Key: {
- mySuperSubKey: '15',
- mySuperSub2Key: 'hello',
- mySuperSub3Key: [ '1', 'hello', 2 ],
- mySuperSub4Key: 4
- },
- mySuper4Key: 45,
- toto: {
- super_key: '15',
- superKey2: 'hello'
- },
- super_key: {
- superKey4: 15
- }
- }
-
- const res = objectConverter(obj, keyConverter, valueConverter)
-
- expect(res.my_super_key).to.equal('hello')
- expect(res.my_super_2_key).to.equal(45)
- expect(res.my_super_3_key.my_super_sub_key).to.equal(15)
- expect(res.my_super_3_key.my_super_sub_2_key).to.equal('hello')
- expect(res.my_super_3_key.my_super_sub_3_key).to.deep.equal([ 1, 'hello', 2 ])
- expect(res.my_super_3_key.my_super_sub_4_key).to.equal(4)
- expect(res.toto.super_key).to.equal(15)
- expect(res.toto.super_key_2).to.equal('hello')
- expect(res.super_key.super_key_4).to.equal(15)
-
- // Immutable
- expect(res.mySuperKey).to.be.undefined
- expect(obj['my_super_key']).to.be.undefined
- })
-})
-
-describe('Bitrate', function () {
-
- it('Should get appropriate max bitrate', function () {
- const tests = [
- { resolution: VideoResolution.H_144P, ratio: 16 / 9, fps: 24, min: 200, max: 400 },
- { resolution: VideoResolution.H_240P, ratio: 16 / 9, fps: 24, min: 600, max: 800 },
- { resolution: VideoResolution.H_360P, ratio: 16 / 9, fps: 24, min: 1200, max: 1600 },
- { resolution: VideoResolution.H_480P, ratio: 16 / 9, fps: 24, min: 2000, max: 2300 },
- { resolution: VideoResolution.H_720P, ratio: 16 / 9, fps: 24, min: 4000, max: 4400 },
- { resolution: VideoResolution.H_1080P, ratio: 16 / 9, fps: 24, min: 8000, max: 10000 },
- { resolution: VideoResolution.H_4K, ratio: 16 / 9, fps: 24, min: 25000, max: 30000 }
- ]
-
- for (const test of tests) {
- expect(getMaxTheoreticalBitrate(test)).to.be.above(test.min * 1000).and.below(test.max * 1000)
- }
- })
-
- it('Should get appropriate average bitrate', function () {
- const tests = [
- { resolution: VideoResolution.H_144P, ratio: 16 / 9, fps: 24, min: 50, max: 300 },
- { resolution: VideoResolution.H_240P, ratio: 16 / 9, fps: 24, min: 350, max: 450 },
- { resolution: VideoResolution.H_360P, ratio: 16 / 9, fps: 24, min: 700, max: 900 },
- { resolution: VideoResolution.H_480P, ratio: 16 / 9, fps: 24, min: 1100, max: 1300 },
- { resolution: VideoResolution.H_720P, ratio: 16 / 9, fps: 24, min: 2300, max: 2500 },
- { resolution: VideoResolution.H_1080P, ratio: 16 / 9, fps: 24, min: 4700, max: 5000 },
- { resolution: VideoResolution.H_4K, ratio: 16 / 9, fps: 24, min: 15000, max: 17000 }
- ]
-
- for (const test of tests) {
- expect(getAverageTheoreticalBitrate(test)).to.be.above(test.min * 1000).and.below(test.max * 1000)
- }
- })
-})
diff --git a/server/tests/helpers/crypto.ts b/server/tests/helpers/crypto.ts
deleted file mode 100644
index b508c715b..000000000
--- a/server/tests/helpers/crypto.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { decrypt, encrypt } from '@server/helpers/peertube-crypto'
-
-describe('Encrypt/Descrypt', function () {
-
- it('Should encrypt and decrypt the string', async function () {
- const secret = 'my_secret'
- const str = 'my super string'
-
- const encrypted = await encrypt(str, secret)
- const decrypted = await decrypt(encrypted, secret)
-
- expect(str).to.equal(decrypted)
- })
-
- it('Should not decrypt without the same secret', async function () {
- const str = 'my super string'
-
- const encrypted = await encrypt(str, 'my_secret')
-
- let error = false
-
- try {
- await decrypt(encrypted, 'my_sicret')
- } catch (err) {
- error = true
- }
-
- expect(error).to.be.true
- })
-})
diff --git a/server/tests/helpers/dns.ts b/server/tests/helpers/dns.ts
deleted file mode 100644
index 49b506e7b..000000000
--- a/server/tests/helpers/dns.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { isResolvingToUnicastOnly } from '@server/helpers/dns'
-
-describe('DNS helpers', function () {
-
- it('Should correctly check unicast IPs', async function () {
- expect(await isResolvingToUnicastOnly('cpy.re')).to.be.true
- expect(await isResolvingToUnicastOnly('framasoft.org')).to.be.true
- expect(await isResolvingToUnicastOnly('8.8.8.8')).to.be.true
-
- expect(await isResolvingToUnicastOnly('127.0.0.1')).to.be.false
- expect(await isResolvingToUnicastOnly('127.0.0.1.cpy.re')).to.be.false
- })
-})
diff --git a/server/tests/helpers/image.ts b/server/tests/helpers/image.ts
deleted file mode 100644
index 6021ffc48..000000000
--- a/server/tests/helpers/image.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { readFile, remove } from 'fs-extra'
-import { join } from 'path'
-import { execPromise } from '@server/helpers/core-utils'
-import { buildAbsoluteFixturePath, root } from '@shared/core-utils'
-import { processImage } from '../../../server/helpers/image-utils'
-
-async function checkBuffers (path1: string, path2: string, equals: boolean) {
- const [ buf1, buf2 ] = await Promise.all([
- readFile(path1),
- readFile(path2)
- ])
-
- if (equals) {
- expect(buf1.equals(buf2)).to.be.true
- } else {
- expect(buf1.equals(buf2)).to.be.false
- }
-}
-
-async function hasTitleExif (path: string) {
- const result = JSON.parse(await execPromise(`exiftool -json ${path}`))
-
- return result[0]?.Title === 'should be removed'
-}
-
-describe('Image helpers', function () {
- const imageDestDir = join(root(), 'test-images')
-
- const imageDestJPG = join(imageDestDir, 'test.jpg')
- const imageDestPNG = join(imageDestDir, 'test.png')
-
- const thumbnailSize = { width: 280, height: 157 }
-
- it('Should skip processing if the source image is okay', async function () {
- const input = buildAbsoluteFixturePath('custom-thumbnail.jpg')
- await processImage({ path: input, destination: imageDestJPG, newSize: thumbnailSize, keepOriginal: true })
-
- await checkBuffers(input, imageDestJPG, true)
- })
-
- it('Should not skip processing if the source image does not have the appropriate extension', async function () {
- const input = buildAbsoluteFixturePath('custom-thumbnail.png')
- await processImage({ path: input, destination: imageDestJPG, newSize: thumbnailSize, keepOriginal: true })
-
- await checkBuffers(input, imageDestJPG, false)
- })
-
- it('Should not skip processing if the source image does not have the appropriate size', async function () {
- const input = buildAbsoluteFixturePath('custom-preview.jpg')
- await processImage({ path: input, destination: imageDestJPG, newSize: thumbnailSize, keepOriginal: true })
-
- await checkBuffers(input, imageDestJPG, false)
- })
-
- it('Should not skip processing if the source image does not have the appropriate size', async function () {
- const input = buildAbsoluteFixturePath('custom-thumbnail-big.jpg')
- await processImage({ path: input, destination: imageDestJPG, newSize: thumbnailSize, keepOriginal: true })
-
- await checkBuffers(input, imageDestJPG, false)
- })
-
- it('Should strip exif for a jpg file that can not be copied', async function () {
- const input = buildAbsoluteFixturePath('exif.jpg')
- expect(await hasTitleExif(input)).to.be.true
-
- await processImage({ path: input, destination: imageDestJPG, newSize: { width: 100, height: 100 }, keepOriginal: true })
- await checkBuffers(input, imageDestJPG, false)
-
- expect(await hasTitleExif(imageDestJPG)).to.be.false
- })
-
- it('Should strip exif for a jpg file that could be copied', async function () {
- const input = buildAbsoluteFixturePath('exif.jpg')
- expect(await hasTitleExif(input)).to.be.true
-
- await processImage({ path: input, destination: imageDestJPG, newSize: thumbnailSize, keepOriginal: true })
- await checkBuffers(input, imageDestJPG, false)
-
- expect(await hasTitleExif(imageDestJPG)).to.be.false
- })
-
- it('Should strip exif for png', async function () {
- const input = buildAbsoluteFixturePath('exif.png')
- expect(await hasTitleExif(input)).to.be.true
-
- await processImage({ path: input, destination: imageDestPNG, newSize: thumbnailSize, keepOriginal: true })
- expect(await hasTitleExif(imageDestPNG)).to.be.false
- })
-
- after(async function () {
- await remove(imageDestDir)
- })
-})
diff --git a/server/tests/helpers/index.ts b/server/tests/helpers/index.ts
deleted file mode 100644
index 073ae6455..000000000
--- a/server/tests/helpers/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import './comment-model'
-import './core-utils'
-import './crypto'
-import './dns'
-import './image'
-import './markdown'
-import './request'
-import './validator'
-import './version'
diff --git a/server/tests/helpers/markdown.ts b/server/tests/helpers/markdown.ts
deleted file mode 100644
index 6fab31d6f..000000000
--- a/server/tests/helpers/markdown.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { mdToOneLinePlainText } from '@server/helpers/markdown'
-import { expect } from 'chai'
-
-describe('Markdown helpers', function () {
-
- describe('Plain text', function () {
-
- it('Should convert a list to plain text', function () {
- const result = mdToOneLinePlainText(`* list 1
-* list 2
-* list 3`)
-
- expect(result).to.equal('list 1, list 2, list 3')
- })
-
- it('Should convert a list with indentation to plain text', function () {
- const result = mdToOneLinePlainText(`Hello:
- * list 1
- * list 2
- * list 3`)
-
- expect(result).to.equal('Hello: list 1, list 2, list 3')
- })
-
- it('Should convert HTML to plain text', function () {
- const result = mdToOneLinePlainText(`**Hello** coucou`)
-
- expect(result).to.equal('Hello coucou')
- })
-
- it('Should convert tags to plain text', function () {
- const result = mdToOneLinePlainText(`#déconversion\n#newage\n#histoire`)
-
- expect(result).to.equal('#déconversion #newage #histoire')
- })
- })
-})
diff --git a/server/tests/helpers/request.ts b/server/tests/helpers/request.ts
deleted file mode 100644
index 363237df5..000000000
--- a/server/tests/helpers/request.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, remove } from 'fs-extra'
-import { join } from 'path'
-import { root, wait } from '@shared/core-utils'
-import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
-import { FIXTURE_URLS, Mock429 } from '../shared'
-
-describe('Request helpers', function () {
- const destPath1 = join(root(), 'test-output-1.txt')
- const destPath2 = join(root(), 'test-output-2.txt')
-
- it('Should throw an error when the bytes limit is exceeded for request', async function () {
- try {
- await doRequest(FIXTURE_URLS.file4K, { bodyKBLimit: 3 })
- } catch {
- return
- }
-
- throw new Error('No error thrown by do request')
- })
-
- it('Should throw an error when the bytes limit is exceeded for request and save file', async function () {
- try {
- await doRequestAndSaveToFile(FIXTURE_URLS.file4K, destPath1, { bodyKBLimit: 3 })
- } catch {
-
- await wait(500)
- expect(await pathExists(destPath1)).to.be.false
- return
- }
-
- throw new Error('No error thrown by do request and save to file')
- })
-
- it('Should correctly retry on 429 error', async function () {
- this.timeout(25000)
-
- const mock = new Mock429()
- const port = await mock.initialize()
-
- const before = new Date().getTime()
- await doRequest('http://127.0.0.1:' + port)
-
- expect(new Date().getTime() - before).to.be.greaterThan(2000)
-
- await mock.terminate()
- })
-
- it('Should succeed if the file is below the limit', async function () {
- await doRequest(FIXTURE_URLS.file4K, { bodyKBLimit: 5 })
- await doRequestAndSaveToFile(FIXTURE_URLS.file4K, destPath2, { bodyKBLimit: 5 })
-
- expect(await pathExists(destPath2)).to.be.true
- })
-
- after(async function () {
- await remove(destPath1)
- await remove(destPath2)
- })
-})
diff --git a/server/tests/helpers/validator.ts b/server/tests/helpers/validator.ts
deleted file mode 100644
index f40a3aaae..000000000
--- a/server/tests/helpers/validator.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { isPluginStableOrUnstableVersionValid, isPluginStableVersionValid } from '@server/helpers/custom-validators/plugins'
-
-describe('Validators', function () {
-
- it('Should correctly check stable plugin versions', async function () {
- expect(isPluginStableVersionValid('3.4.0')).to.be.true
- expect(isPluginStableVersionValid('0.4.0')).to.be.true
- expect(isPluginStableVersionValid('0.1.0')).to.be.true
-
- expect(isPluginStableVersionValid('0.1.0-beta-1')).to.be.false
- expect(isPluginStableVersionValid('hello')).to.be.false
- expect(isPluginStableVersionValid('0.x.a')).to.be.false
- })
-
- it('Should correctly check unstable plugin versions', async function () {
- expect(isPluginStableOrUnstableVersionValid('3.4.0')).to.be.true
- expect(isPluginStableOrUnstableVersionValid('0.4.0')).to.be.true
- expect(isPluginStableOrUnstableVersionValid('0.1.0')).to.be.true
-
- expect(isPluginStableOrUnstableVersionValid('0.1.0-beta.1')).to.be.true
- expect(isPluginStableOrUnstableVersionValid('0.1.0-alpha.45')).to.be.true
- expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45')).to.be.true
-
- expect(isPluginStableOrUnstableVersionValid('hello')).to.be.false
- expect(isPluginStableOrUnstableVersionValid('0.x.a')).to.be.false
- expect(isPluginStableOrUnstableVersionValid('0.1.0-rc-45')).to.be.false
- expect(isPluginStableOrUnstableVersionValid('0.1.0-rc.45d')).to.be.false
- })
-})
diff --git a/server/tests/helpers/version.ts b/server/tests/helpers/version.ts
deleted file mode 100644
index 2a90efba3..000000000
--- a/server/tests/helpers/version.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { compareSemVer } from '@shared/core-utils'
-
-describe('Version', function () {
-
- it('Should correctly compare two stable versions', async function () {
- expect(compareSemVer('3.4.0', '3.5.0')).to.be.below(0)
- expect(compareSemVer('3.5.0', '3.4.0')).to.be.above(0)
-
- expect(compareSemVer('3.4.0', '4.1.0')).to.be.below(0)
- expect(compareSemVer('4.1.0', '3.4.0')).to.be.above(0)
-
- expect(compareSemVer('3.4.0', '3.4.1')).to.be.below(0)
- expect(compareSemVer('3.4.1', '3.4.0')).to.be.above(0)
- })
-
- it('Should correctly compare two unstable version', async function () {
- expect(compareSemVer('3.4.0-alpha', '3.4.0-beta.1')).to.be.below(0)
- expect(compareSemVer('3.4.0-alpha.1', '3.4.0-beta.1')).to.be.below(0)
- expect(compareSemVer('3.4.0-beta.1', '3.4.0-beta.2')).to.be.below(0)
- expect(compareSemVer('3.4.0-beta.1', '3.5.0-alpha.1')).to.be.below(0)
-
- expect(compareSemVer('3.4.0-alpha.1', '3.4.0-nightly.4')).to.be.below(0)
- expect(compareSemVer('3.4.0-nightly.3', '3.4.0-nightly.4')).to.be.below(0)
- expect(compareSemVer('3.3.0-nightly.5', '3.4.0-nightly.4')).to.be.below(0)
- })
-
- it('Should correctly compare a stable and unstable versions', async function () {
- expect(compareSemVer('3.4.0', '3.4.1-beta.1')).to.be.below(0)
- expect(compareSemVer('3.4.0-beta.1', '3.4.0-beta.2')).to.be.below(0)
- expect(compareSemVer('3.4.0-beta.1', '3.4.0')).to.be.below(0)
- expect(compareSemVer('3.4.0-nightly.4', '3.4.0')).to.be.below(0)
- })
-})
diff --git a/server/tests/index.ts b/server/tests/index.ts
deleted file mode 100644
index 4ec1ebe67..000000000
--- a/server/tests/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// Order of the tests we want to execute
-import './client'
-import './misc-endpoints'
-import './feeds/'
-import './cli/'
-import './api/'
-import './peertube-runner/'
-import './plugins/'
-import './helpers/'
-import './lib/'
diff --git a/server/tests/lib/index.ts b/server/tests/lib/index.ts
deleted file mode 100644
index a40df35fd..000000000
--- a/server/tests/lib/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './video-constant-registry-factory'
diff --git a/server/tests/lib/video-constant-registry-factory.ts b/server/tests/lib/video-constant-registry-factory.ts
deleted file mode 100644
index c3480dc12..000000000
--- a/server/tests/lib/video-constant-registry-factory.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions */
-import { expect } from 'chai'
-import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
-import {
- VIDEO_CATEGORIES,
- VIDEO_LANGUAGES,
- VIDEO_LICENCES,
- VIDEO_PLAYLIST_PRIVACIES,
- VIDEO_PRIVACIES
-} from '@server/initializers/constants'
-import {
- VideoPlaylistPrivacy,
- VideoPrivacy
-} from '@shared/models'
-
-describe('VideoConstantManagerFactory', function () {
- const factory = new VideoConstantManagerFactory('peertube-plugin-constants')
-
- afterEach(() => {
- factory.resetVideoConstants('peertube-plugin-constants')
- })
-
- describe('VideoCategoryManager', () => {
- const videoCategoryManager = factory.createVideoConstantManager('category')
-
- it('Should be able to list all video category constants', () => {
- const constants = videoCategoryManager.getConstants()
- expect(constants).to.deep.equal(VIDEO_CATEGORIES)
- })
-
- it('Should be able to delete a video category constant', () => {
- const successfullyDeleted = videoCategoryManager.deleteConstant(1)
- expect(successfullyDeleted).to.be.true
- expect(videoCategoryManager.getConstantValue(1)).to.be.undefined
- })
-
- it('Should be able to add a video category constant', () => {
- const successfullyAdded = videoCategoryManager.addConstant(42, 'The meaning of life')
- expect(successfullyAdded).to.be.true
- expect(videoCategoryManager.getConstantValue(42)).to.equal('The meaning of life')
- })
-
- it('Should be able to reset video category constants', () => {
- videoCategoryManager.deleteConstant(1)
- videoCategoryManager.resetConstants()
- expect(videoCategoryManager.getConstantValue(1)).not.be.undefined
- })
- })
-
- describe('VideoLicenceManager', () => {
- const videoLicenceManager = factory.createVideoConstantManager('licence')
- it('Should be able to list all video licence constants', () => {
- const constants = videoLicenceManager.getConstants()
- expect(constants).to.deep.equal(VIDEO_LICENCES)
- })
-
- it('Should be able to delete a video licence constant', () => {
- const successfullyDeleted = videoLicenceManager.deleteConstant(1)
- expect(successfullyDeleted).to.be.true
- expect(videoLicenceManager.getConstantValue(1)).to.be.undefined
- })
-
- it('Should be able to add a video licence constant', () => {
- const successfullyAdded = videoLicenceManager.addConstant(42, 'European Union Public Licence')
- expect(successfullyAdded).to.be.true
- expect(videoLicenceManager.getConstantValue(42 as any)).to.equal('European Union Public Licence')
- })
-
- it('Should be able to reset video licence constants', () => {
- videoLicenceManager.deleteConstant(1)
- videoLicenceManager.resetConstants()
- expect(videoLicenceManager.getConstantValue(1)).not.be.undefined
- })
- })
-
- describe('PlaylistPrivacyManager', () => {
- const playlistPrivacyManager = factory.createVideoConstantManager('playlistPrivacy')
- it('Should be able to list all video playlist privacy constants', () => {
- const constants = playlistPrivacyManager.getConstants()
- expect(constants).to.deep.equal(VIDEO_PLAYLIST_PRIVACIES)
- })
-
- it('Should be able to delete a video playlist privacy constant', () => {
- const successfullyDeleted = playlistPrivacyManager.deleteConstant(1)
- expect(successfullyDeleted).to.be.true
- expect(playlistPrivacyManager.getConstantValue(1)).to.be.undefined
- })
-
- it('Should be able to add a video playlist privacy constant', () => {
- const successfullyAdded = playlistPrivacyManager.addConstant(42 as any, 'Friends only')
- expect(successfullyAdded).to.be.true
- expect(playlistPrivacyManager.getConstantValue(42 as any)).to.equal('Friends only')
- })
-
- it('Should be able to reset video playlist privacy constants', () => {
- playlistPrivacyManager.deleteConstant(1)
- playlistPrivacyManager.resetConstants()
- expect(playlistPrivacyManager.getConstantValue(1)).not.be.undefined
- })
- })
-
- describe('VideoPrivacyManager', () => {
- const videoPrivacyManager = factory.createVideoConstantManager('privacy')
- it('Should be able to list all video privacy constants', () => {
- const constants = videoPrivacyManager.getConstants()
- expect(constants).to.deep.equal(VIDEO_PRIVACIES)
- })
-
- it('Should be able to delete a video privacy constant', () => {
- const successfullyDeleted = videoPrivacyManager.deleteConstant(1)
- expect(successfullyDeleted).to.be.true
- expect(videoPrivacyManager.getConstantValue(1)).to.be.undefined
- })
-
- it('Should be able to add a video privacy constant', () => {
- const successfullyAdded = videoPrivacyManager.addConstant(42 as any, 'Friends only')
- expect(successfullyAdded).to.be.true
- expect(videoPrivacyManager.getConstantValue(42 as any)).to.equal('Friends only')
- })
-
- it('Should be able to reset video privacy constants', () => {
- videoPrivacyManager.deleteConstant(1)
- videoPrivacyManager.resetConstants()
- expect(videoPrivacyManager.getConstantValue(1)).not.be.undefined
- })
- })
-
- describe('VideoLanguageManager', () => {
- const videoLanguageManager = factory.createVideoConstantManager('language')
- it('Should be able to list all video language constants', () => {
- const constants = videoLanguageManager.getConstants()
- expect(constants).to.deep.equal(VIDEO_LANGUAGES)
- })
-
- it('Should be able to add a video language constant', () => {
- const successfullyAdded = videoLanguageManager.addConstant('fr', 'Fr occitan')
- expect(successfullyAdded).to.be.true
- expect(videoLanguageManager.getConstantValue('fr')).to.equal('Fr occitan')
- })
-
- it('Should be able to delete a video language constant', () => {
- videoLanguageManager.addConstant('fr', 'Fr occitan')
- const successfullyDeleted = videoLanguageManager.deleteConstant('fr')
- expect(successfullyDeleted).to.be.true
- expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
- })
-
- it('Should be able to reset video language constants', () => {
- videoLanguageManager.addConstant('fr', 'Fr occitan')
- videoLanguageManager.resetConstants()
- expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
- })
- })
-})
diff --git a/server/tests/misc-endpoints.ts b/server/tests/misc-endpoints.ts
deleted file mode 100644
index f9cf2b717..000000000
--- a/server/tests/misc-endpoints.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { writeJson } from 'fs-extra'
-import { join } from 'path'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
-import { expectLogDoesNotContain } from './shared'
-
-describe('Test misc endpoints', function () {
- let server: PeerTubeServer
- let wellKnownPath: string
-
- before(async function () {
- this.timeout(120000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
-
- wellKnownPath = server.getDirectoryPath('well-known')
- })
-
- describe('Test a well known endpoints', function () {
-
- it('Should get security.txt', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/security.txt',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('security issue')
- })
-
- it('Should get nodeinfo', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/nodeinfo',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.links).to.be.an('array')
- expect(res.body.links).to.have.lengthOf(1)
- expect(res.body.links[0].rel).to.equal('http://nodeinfo.diaspora.software/ns/schema/2.0')
- })
-
- it('Should get dnt policy text', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/dnt-policy.txt',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('http://www.w3.org/TR/tracking-dnt')
- })
-
- it('Should get dnt policy', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/dnt',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.tracking).to.equal('N')
- })
-
- it('Should get change-password location', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/change-password',
- expectedStatus: HttpStatusCode.FOUND_302
- })
-
- expect(res.header.location).to.equal('/my-account/settings')
- })
-
- it('Should test webfinger', async function () {
- const resource = 'acct:peertube@' + server.host
- const accountUrl = server.url + '/accounts/peertube'
-
- const res = await makeGetRequest({
- url: server.url,
- path: '/.well-known/webfinger?resource=' + resource,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const data = res.body
-
- expect(data.subject).to.equal(resource)
- expect(data.aliases).to.contain(accountUrl)
-
- const self = data.links.find(l => l.rel === 'self')
- expect(self).to.exist
- expect(self.type).to.equal('application/activity+json')
- expect(self.href).to.equal(accountUrl)
-
- const remoteInteract = data.links.find(l => l.rel === 'http://ostatus.org/schema/1.0/subscribe')
- expect(remoteInteract).to.exist
- expect(remoteInteract.template).to.equal(server.url + '/remote-interaction?uri={uri}')
- })
-
- it('Should return 404 for non-existing files in /.well-known', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/.well-known/non-existing-file',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should return custom file from /.well-known', async function () {
- const filename = 'existing-file.json'
-
- await writeJson(join(wellKnownPath, filename), { iThink: 'therefore I am' })
-
- const { body } = await makeGetRequest({
- url: server.url,
- path: '/.well-known/' + filename,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(body.iThink).to.equal('therefore I am')
- })
- })
-
- describe('Test classic static endpoints', function () {
-
- it('Should get robots.txt', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/robots.txt',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('User-agent')
- })
-
- it('Should get security.txt', async function () {
- await makeGetRequest({
- url: server.url,
- path: '/security.txt',
- expectedStatus: HttpStatusCode.MOVED_PERMANENTLY_301
- })
- })
-
- it('Should get nodeinfo', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/nodeinfo/2.0.json',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.software.name).to.equal('peertube')
- expect(res.body.usage.users.activeMonth).to.equal(1)
- expect(res.body.usage.users.activeHalfyear).to.equal(1)
- })
- })
-
- describe('Test bots endpoints', function () {
-
- it('Should get the empty sitemap', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/sitemap.xml',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
- expect(res.text).to.contain('' + server.url + '/about/instance')
- })
-
- it('Should get the empty cached sitemap', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: '/sitemap.xml',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
- expect(res.text).to.contain('' + server.url + '/about/instance')
- })
-
- it('Should add videos, channel and accounts and get sitemap', async function () {
- this.timeout(35000)
-
- await server.videos.upload({ attributes: { name: 'video 1', nsfw: false } })
- await server.videos.upload({ attributes: { name: 'video 2', nsfw: false } })
- await server.videos.upload({ attributes: { name: 'video 3', privacy: VideoPrivacy.PRIVATE } })
-
- await server.channels.create({ attributes: { name: 'channel1', displayName: 'channel 1' } })
- await server.channels.create({ attributes: { name: 'channel2', displayName: 'channel 2' } })
-
- await server.users.create({ username: 'user1', password: 'password' })
- await server.users.create({ username: 'user2', password: 'password' })
-
- const res = await makeGetRequest({
- url: server.url,
- path: '/sitemap.xml?t=1', // avoid using cache
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.text).to.contain('xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"')
- expect(res.text).to.contain('' + server.url + '/about/instance')
-
- expect(res.text).to.contain('video 1')
- expect(res.text).to.contain('video 2')
- expect(res.text).to.not.contain('video 3')
-
- expect(res.text).to.contain('' + server.url + '/video-channels/channel1')
- expect(res.text).to.contain('' + server.url + '/video-channels/channel2')
-
- expect(res.text).to.contain('' + server.url + '/accounts/user1')
- expect(res.text).to.contain('' + server.url + '/accounts/user2')
- })
-
- it('Should not fail with big title/description videos', async function () {
- const name = 'v'.repeat(115)
-
- await server.videos.upload({ attributes: { name, description: 'd'.repeat(2500), nsfw: false } })
-
- const res = await makeGetRequest({
- url: server.url,
- path: '/sitemap.xml?t=2', // avoid using cache
- expectedStatus: HttpStatusCode.OK_200
- })
-
- await expectLogDoesNotContain(server, 'Warning in sitemap generation')
- await expectLogDoesNotContain(server, 'Error in sitemap generation')
-
- expect(res.text).to.contain(`${'v'.repeat(97)}...`)
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/peertube-runner/client-cli.ts b/server/tests/peertube-runner/client-cli.ts
deleted file mode 100644
index 5cbdc4e77..000000000
--- a/server/tests/peertube-runner/client-cli.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { PeerTubeRunnerProcess } from '@server/tests/shared'
-import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/server-commands'
-
-describe('Test peertube-runner program client CLI', function () {
- let server: PeerTubeServer
- let peertubeRunner: PeerTubeRunnerProcess
-
- before(async function () {
- this.timeout(120_000)
-
- server = await createSingleServer(1)
-
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await server.config.enableRemoteTranscoding()
-
- peertubeRunner = new PeerTubeRunnerProcess(server)
- await peertubeRunner.runServer()
- })
-
- it('Should not have PeerTube instance listed', async function () {
- const data = await peertubeRunner.listRegisteredPeerTubeInstances()
-
- expect(data).to.not.contain(server.url)
- })
-
- it('Should register a new PeerTube instance', async function () {
- const registrationToken = await server.runnerRegistrationTokens.getFirstRegistrationToken()
-
- await peertubeRunner.registerPeerTubeInstance({
- registrationToken,
- runnerName: 'my super runner',
- runnerDescription: 'super description'
- })
- })
-
- it('Should list this new PeerTube instance', async function () {
- const data = await peertubeRunner.listRegisteredPeerTubeInstances()
-
- expect(data).to.contain(server.url)
- expect(data).to.contain('my super runner')
- expect(data).to.contain('super description')
- })
-
- it('Should still have the configuration after a restart', async function () {
- peertubeRunner.kill()
-
- await peertubeRunner.runServer()
- })
-
- it('Should unregister the PeerTube instance', async function () {
- await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'my super runner' })
- })
-
- it('Should not have PeerTube instance listed', async function () {
- const data = await peertubeRunner.listRegisteredPeerTubeInstances()
-
- expect(data).to.not.contain(server.url)
- })
-
- after(async function () {
- peertubeRunner.kill()
-
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/peertube-runner/index.ts b/server/tests/peertube-runner/index.ts
deleted file mode 100644
index 470316417..000000000
--- a/server/tests/peertube-runner/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './client-cli'
-export * from './live-transcoding'
-export * from './studio-transcoding'
-export * from './vod-transcoding'
diff --git a/server/tests/peertube-runner/live-transcoding.ts b/server/tests/peertube-runner/live-transcoding.ts
deleted file mode 100644
index 41b01f8d5..000000000
--- a/server/tests/peertube-runner/live-transcoding.ts
+++ /dev/null
@@ -1,201 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { expect } from 'chai'
-import {
- checkPeerTubeRunnerCacheIsEmpty,
- expectStartWith,
- PeerTubeRunnerProcess,
- SQLCommand,
- testLiveVideoResolutions
-} from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled, wait } from '@shared/core-utils'
-import { HttpStatusCode, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- findExternalSavedVideo,
- makeRawRequest,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs,
- waitUntilLivePublishedOnAllServers,
- waitUntilLiveWaitingOnAllServers
-} from '@shared/server-commands'
-
-describe('Test Live transcoding in peertube-runner program', function () {
- let servers: PeerTubeServer[] = []
- let peertubeRunner: PeerTubeRunnerProcess
- let sqlCommandServer1: SQLCommand
-
- function runSuite (options: {
- objectStorage?: ObjectStorageCommand
- } = {}) {
- const { objectStorage } = options
-
- it('Should enable transcoding without additional resolutions', async function () {
- this.timeout(120000)
-
- const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC })
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid })
- await waitUntilLivePublishedOnAllServers(servers, video.uuid)
- await waitJobs(servers)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: video.uuid,
- resolutions: [ 720, 480, 360, 240, 144 ],
- objectStorage,
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
- await servers[0].videos.remove({ id: video.id })
- })
-
- it('Should transcode audio only RTMP stream', async function () {
- this.timeout(120000)
-
- const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.UNLISTED })
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid, fixtureName: 'video_short_no_audio.mp4' })
- await waitUntilLivePublishedOnAllServers(servers, video.uuid)
- await waitJobs(servers)
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
- await servers[0].videos.remove({ id: video.id })
- })
-
- it('Should save a replay', async function () {
- this.timeout(240000)
-
- const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: true })
-
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid })
- await waitUntilLivePublishedOnAllServers(servers, video.uuid)
-
- await testLiveVideoResolutions({
- originServer: servers[0],
- sqlCommand: sqlCommandServer1,
- servers,
- liveVideoId: video.uuid,
- resolutions: [ 720, 480, 360, 240, 144 ],
- objectStorage,
- transcoded: true
- })
-
- await stopFfmpeg(ffmpegCommand)
-
- await waitUntilLiveWaitingOnAllServers(servers, video.uuid)
- await waitJobs(servers)
-
- const session = await servers[0].live.findLatestSession({ videoId: video.uuid })
- expect(session.endingProcessed).to.be.true
- expect(session.endDate).to.exist
- expect(session.saveReplay).to.be.true
-
- const videoLiveDetails = await servers[0].videos.get({ id: video.uuid })
- const replay = await findExternalSavedVideo(servers[0], videoLiveDetails)
-
- for (const server of servers) {
- const video = await server.videos.get({ id: replay.uuid })
-
- expect(video.files).to.have.lengthOf(0)
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const files = video.streamingPlaylists[0].files
- expect(files).to.have.lengthOf(5)
-
- for (const file of files) {
- if (objectStorage) {
- expectStartWith(file.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- }
-
- await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
- }
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- sqlCommandServer1 = new SQLCommand(servers[0])
-
- await servers[0].config.enableRemoteTranscoding()
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
- await servers[0].config.enableLive({ allowReplay: true, resolutions: 'max', transcoding: true })
-
- const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken()
-
- peertubeRunner = new PeerTubeRunnerProcess(servers[0])
- await peertubeRunner.runServer()
- await peertubeRunner.registerPeerTubeInstance({ registrationToken, runnerName: 'runner' })
- })
-
- describe('With lives on local filesystem storage', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ webVideo: true, hls: false, with0p: true })
- })
-
- runSuite()
- })
-
- describe('With lives on object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
-
- await servers[0].run(objectStorage.getDefaultMockConfig())
-
- // Wait for peertube runner socket reconnection
- await wait(1500)
- })
-
- runSuite({ objectStorage })
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- describe('Check cleanup', function () {
-
- it('Should have an empty cache directory', async function () {
- await checkPeerTubeRunnerCacheIsEmpty(peertubeRunner)
- })
- })
-
- after(async function () {
- if (peertubeRunner) {
- await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'runner' })
- peertubeRunner.kill()
- }
-
- if (sqlCommandServer1) await sqlCommandServer1.cleanup()
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/peertube-runner/studio-transcoding.ts b/server/tests/peertube-runner/studio-transcoding.ts
deleted file mode 100644
index 56bfef897..000000000
--- a/server/tests/peertube-runner/studio-transcoding.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-
-import { expect } from 'chai'
-import { checkPeerTubeRunnerCacheIsEmpty, checkVideoDuration, expectStartWith, PeerTubeRunnerProcess } from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled, getAllFiles, wait } from '@shared/core-utils'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- VideoStudioCommand,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test studio transcoding in peertube-runner program', function () {
- let servers: PeerTubeServer[] = []
- let peertubeRunner: PeerTubeRunnerProcess
-
- function runSuite (options: {
- objectStorage?: ObjectStorageCommand
- } = {}) {
- const { objectStorage } = options
-
- it('Should run a complex studio transcoding', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.mp4' })
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
- const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
-
- await servers[0].videoStudio.createEditionTasks({ videoId: uuid, tasks: VideoStudioCommand.getComplexTask() })
- await waitJobs(servers, { runnerJobs: true })
-
- for (const server of servers) {
- const video = await server.videos.get({ id: uuid })
- const files = getAllFiles(video)
-
- for (const f of files) {
- expect(oldFileUrls).to.not.include(f.fileUrl)
- }
-
- if (objectStorage) {
- for (const webVideoFile of video.files) {
- expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
- }
-
- for (const hlsFile of video.streamingPlaylists[0].files) {
- expectStartWith(hlsFile.fileUrl, objectStorage.getMockPlaylistBaseUrl())
- }
- }
-
- await checkVideoDuration(server, uuid, 9)
- }
- })
- }
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true })
- await servers[0].config.enableStudio()
- await servers[0].config.enableRemoteStudio()
-
- const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken()
-
- peertubeRunner = new PeerTubeRunnerProcess(servers[0])
- await peertubeRunner.runServer()
- await peertubeRunner.registerPeerTubeInstance({ registrationToken, runnerName: 'runner' })
- })
-
- describe('With videos on local filesystem storage', function () {
- runSuite()
- })
-
- describe('With videos on object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
-
- await servers[0].run(objectStorage.getDefaultMockConfig())
-
- // Wait for peertube runner socket reconnection
- await wait(1500)
- })
-
- runSuite({ objectStorage })
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- describe('Check cleanup', function () {
-
- it('Should have an empty cache directory', async function () {
- await checkPeerTubeRunnerCacheIsEmpty(peertubeRunner)
- })
- })
-
- after(async function () {
- if (peertubeRunner) {
- await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'runner' })
- peertubeRunner.kill()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/peertube-runner/vod-transcoding.ts b/server/tests/peertube-runner/vod-transcoding.ts
deleted file mode 100644
index b3b62e5e0..000000000
--- a/server/tests/peertube-runner/vod-transcoding.ts
+++ /dev/null
@@ -1,350 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-import { expect } from 'chai'
-import {
- checkPeerTubeRunnerCacheIsEmpty,
- completeCheckHlsPlaylist,
- completeWebVideoFilesCheck,
- PeerTubeRunnerProcess
-} from '@server/tests/shared'
-import { areMockObjectStorageTestsDisabled, getAllFiles, wait } from '@shared/core-utils'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- ObjectStorageCommand,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test VOD transcoding in peertube-runner program', function () {
- let servers: PeerTubeServer[] = []
- let peertubeRunner: PeerTubeRunnerProcess
-
- function runSuite (options: {
- webVideoEnabled: boolean
- hlsEnabled: boolean
- objectStorage?: ObjectStorageCommand
- }) {
- const { webVideoEnabled, hlsEnabled, objectStorage } = options
-
- const objectStorageBaseUrlWebVideo = objectStorage
- ? objectStorage.getMockWebVideosBaseUrl()
- : undefined
-
- const objectStorageBaseUrlHLS = objectStorage
- ? objectStorage.getMockPlaylistBaseUrl()
- : undefined
-
- it('Should upload a classic video mp4 and transcode it', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.mp4' })
-
- await waitJobs(servers, { runnerJobs: true })
-
- for (const server of servers) {
- if (webVideoEnabled) {
- await completeWebVideoFilesCheck({
- server,
- originServer: servers[0],
- fixture: 'video_short.mp4',
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
- files: [
- { resolution: 0 },
- { resolution: 144 },
- { resolution: 240 },
- { resolution: 360 },
- { resolution: 480 },
- { resolution: 720 }
- ]
- })
- }
-
- if (hlsEnabled) {
- await completeCheckHlsPlaylist({
- hlsOnly: !webVideoEnabled,
- servers,
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlHLS,
- resolutions: [ 720, 480, 360, 240, 144, 0 ]
- })
- }
- }
- })
-
- it('Should upload a webm video and transcode it', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.webm' })
-
- await waitJobs(servers, { runnerJobs: true })
-
- for (const server of servers) {
- if (webVideoEnabled) {
- await completeWebVideoFilesCheck({
- server,
- originServer: servers[0],
- fixture: 'video_short.webm',
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
- files: [
- { resolution: 0 },
- { resolution: 144 },
- { resolution: 240 },
- { resolution: 360 },
- { resolution: 480 },
- { resolution: 720 }
- ]
- })
- }
-
- if (hlsEnabled) {
- await completeCheckHlsPlaylist({
- hlsOnly: !webVideoEnabled,
- servers,
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlHLS,
- resolutions: [ 720, 480, 360, 240, 144, 0 ]
- })
- }
- }
- })
-
- it('Should upload an audio only video and transcode it', async function () {
- this.timeout(120000)
-
- const attributes = { name: 'audio_without_preview', fixture: 'sample.ogg' }
- const { uuid } = await servers[0].videos.upload({ attributes, mode: 'resumable' })
-
- await waitJobs(servers, { runnerJobs: true })
-
- for (const server of servers) {
- if (webVideoEnabled) {
- await completeWebVideoFilesCheck({
- server,
- originServer: servers[0],
- fixture: 'sample.ogg',
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
- files: [
- { resolution: 0 },
- { resolution: 144 },
- { resolution: 240 },
- { resolution: 360 },
- { resolution: 480 }
- ]
- })
- }
-
- if (hlsEnabled) {
- await completeCheckHlsPlaylist({
- hlsOnly: !webVideoEnabled,
- servers,
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlHLS,
- resolutions: [ 480, 360, 240, 144, 0 ]
- })
- }
- }
- })
-
- it('Should upload a private video and transcode it', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'mp4', fixture: 'video_short.mp4', privacy: VideoPrivacy.PRIVATE })
-
- await waitJobs(servers, { runnerJobs: true })
-
- if (webVideoEnabled) {
- await completeWebVideoFilesCheck({
- server: servers[0],
- originServer: servers[0],
- fixture: 'video_short.mp4',
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
- files: [
- { resolution: 0 },
- { resolution: 144 },
- { resolution: 240 },
- { resolution: 360 },
- { resolution: 480 },
- { resolution: 720 }
- ]
- })
- }
-
- if (hlsEnabled) {
- await completeCheckHlsPlaylist({
- hlsOnly: !webVideoEnabled,
- servers: [ servers[0] ],
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlHLS,
- resolutions: [ 720, 480, 360, 240, 144, 0 ]
- })
- }
- })
-
- it('Should transcode videos on manual run', async function () {
- this.timeout(120000)
-
- await servers[0].config.disableTranscoding()
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'manual transcoding', fixture: 'video_short.mp4' })
- await waitJobs(servers, { runnerJobs: true })
-
- {
- const video = await servers[0].videos.get({ id: uuid })
- expect(getAllFiles(video)).to.have.lengthOf(1)
- }
-
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
-
- await servers[0].videos.runTranscoding({ transcodingType: 'web-video', videoId: uuid })
- await waitJobs(servers, { runnerJobs: true })
-
- await completeWebVideoFilesCheck({
- server: servers[0],
- originServer: servers[0],
- fixture: 'video_short.mp4',
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
- files: [
- { resolution: 0 },
- { resolution: 144 },
- { resolution: 240 },
- { resolution: 360 },
- { resolution: 480 },
- { resolution: 720 }
- ]
- })
-
- await servers[0].videos.runTranscoding({ transcodingType: 'hls', videoId: uuid })
- await waitJobs(servers, { runnerJobs: true })
-
- await completeCheckHlsPlaylist({
- hlsOnly: false,
- servers: [ servers[0] ],
- videoUUID: uuid,
- objectStorageBaseUrl: objectStorageBaseUrlHLS,
- resolutions: [ 720, 480, 360, 240, 144, 0 ]
- })
- })
- }
-
- before(async function () {
- this.timeout(120_000)
-
- servers = await createMultipleServers(2)
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].config.enableRemoteTranscoding()
-
- const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken()
-
- peertubeRunner = new PeerTubeRunnerProcess(servers[0])
- await peertubeRunner.runServer()
- await peertubeRunner.registerPeerTubeInstance({ registrationToken, runnerName: 'runner' })
- })
-
- describe('With videos on local filesystem storage', function () {
-
- describe('Web video only enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ webVideo: true, hls: false, with0p: true })
- })
-
- runSuite({ webVideoEnabled: true, hlsEnabled: false })
- })
-
- describe('HLS videos only enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ webVideo: false, hls: true, with0p: true })
- })
-
- runSuite({ webVideoEnabled: false, hlsEnabled: true })
- })
-
- describe('Web video & HLS enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
- })
-
- runSuite({ webVideoEnabled: true, hlsEnabled: true })
- })
- })
-
- describe('With videos on object storage', function () {
- if (areMockObjectStorageTestsDisabled()) return
-
- const objectStorage = new ObjectStorageCommand()
-
- before(async function () {
- await objectStorage.prepareDefaultMockBuckets()
-
- await servers[0].kill()
-
- await servers[0].run(objectStorage.getDefaultMockConfig())
-
- // Wait for peertube runner socket reconnection
- await wait(1500)
- })
-
- describe('Web video only enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ webVideo: true, hls: false, with0p: true })
- })
-
- runSuite({ webVideoEnabled: true, hlsEnabled: false, objectStorage })
- })
-
- describe('HLS videos only enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ webVideo: false, hls: true, with0p: true })
- })
-
- runSuite({ webVideoEnabled: false, hlsEnabled: true, objectStorage })
- })
-
- describe('Web video & HLS enabled', function () {
-
- before(async function () {
- await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true })
- })
-
- runSuite({ webVideoEnabled: true, hlsEnabled: true, objectStorage })
- })
-
- after(async function () {
- await objectStorage.cleanupMock()
- })
- })
-
- describe('Check cleanup', function () {
-
- it('Should have an empty cache directory', async function () {
- await checkPeerTubeRunnerCacheIsEmpty(peertubeRunner)
- })
- })
-
- after(async function () {
- if (peertubeRunner) {
- await peertubeRunner.unregisterPeerTubeInstance({ runnerName: 'runner' })
- peertubeRunner.kill()
- }
-
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts
deleted file mode 100644
index 773be0d76..000000000
--- a/server/tests/plugins/action-hooks.ts
+++ /dev/null
@@ -1,298 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { ServerHookName, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- killallServers,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- stopFfmpeg,
- waitJobs
-} from '@shared/server-commands'
-
-describe('Test plugin action hooks', function () {
- let servers: PeerTubeServer[]
- let videoUUID: string
- let threadId: number
-
- function checkHook (hook: ServerHookName, strictCount = true, count = 1) {
- return servers[0].servers.waitUntilLog('Run hook ' + hook, count, strictCount)
- }
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
-
- await killallServers([ servers[0] ])
-
- await servers[0].run({
- live: {
- enabled: true
- }
- })
-
- await servers[0].config.enableFileUpdate()
-
- await doubleFollow(servers[0], servers[1])
- })
-
- describe('Application hooks', function () {
- it('Should run action:application.listening', async function () {
- await checkHook('action:application.listening')
- })
- })
-
- describe('Videos hooks', function () {
-
- it('Should run action:api.video.uploaded', async function () {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' } })
- videoUUID = uuid
-
- await checkHook('action:api.video.uploaded')
- })
-
- it('Should run action:api.video.updated', async function () {
- await servers[0].videos.update({ id: videoUUID, attributes: { name: 'video updated' } })
-
- await checkHook('action:api.video.updated')
- })
-
- it('Should run action:api.video.viewed', async function () {
- await servers[0].views.simulateView({ id: videoUUID })
-
- await checkHook('action:api.video.viewed')
- })
-
- it('Should run action:api.video.file-updated', async function () {
- await servers[0].videos.replaceSourceFile({ videoId: videoUUID, fixture: 'video_short.mp4' })
-
- await checkHook('action:api.video.file-updated')
- })
-
- it('Should run action:api.video.deleted', async function () {
- await servers[0].videos.remove({ id: videoUUID })
-
- await checkHook('action:api.video.deleted')
- })
-
- after(async function () {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
- videoUUID = uuid
- })
- })
-
- describe('Video channel hooks', function () {
- const channelName = 'my_super_channel'
-
- it('Should run action:api.video-channel.created', async function () {
- await servers[0].channels.create({ attributes: { name: channelName } })
-
- await checkHook('action:api.video-channel.created')
- })
-
- it('Should run action:api.video-channel.updated', async function () {
- await servers[0].channels.update({ channelName, attributes: { displayName: 'my display name' } })
-
- await checkHook('action:api.video-channel.updated')
- })
-
- it('Should run action:api.video-channel.deleted', async function () {
- await servers[0].channels.delete({ channelName })
-
- await checkHook('action:api.video-channel.deleted')
- })
- })
-
- describe('Live hooks', function () {
-
- it('Should run action:api.live-video.created', async function () {
- const attributes = {
- name: 'live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id
- }
-
- await servers[0].live.create({ fields: attributes })
-
- await checkHook('action:api.live-video.created')
- })
-
- it('Should run action:live.video.state.updated', async function () {
- this.timeout(60000)
-
- const attributes = {
- name: 'live',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id
- }
-
- const { uuid: liveVideoId } = await servers[0].live.create({ fields: attributes })
- const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId })
- await servers[0].live.waitUntilPublished({ videoId: liveVideoId })
- await waitJobs(servers)
-
- await checkHook('action:live.video.state.updated', true, 1)
-
- await stopFfmpeg(ffmpegCommand)
- await servers[0].live.waitUntilEnded({ videoId: liveVideoId })
- await waitJobs(servers)
-
- await checkHook('action:live.video.state.updated', true, 2)
- })
- })
-
- describe('Comments hooks', function () {
- it('Should run action:api.video-thread.created', async function () {
- const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
- threadId = created.id
-
- await checkHook('action:api.video-thread.created')
- })
-
- it('Should run action:api.video-comment-reply.created', async function () {
- await servers[0].comments.addReply({ videoId: videoUUID, toCommentId: threadId, text: 'reply' })
-
- await checkHook('action:api.video-comment-reply.created')
- })
-
- it('Should run action:api.video-comment.deleted', async function () {
- await servers[0].comments.delete({ videoId: videoUUID, commentId: threadId })
-
- await checkHook('action:api.video-comment.deleted')
- })
- })
-
- describe('Captions hooks', function () {
- it('Should run action:api.video-caption.created', async function () {
- await servers[0].captions.add({ videoId: videoUUID, language: 'en', fixture: 'subtitle-good.srt' })
-
- await checkHook('action:api.video-caption.created')
- })
-
- it('Should run action:api.video-caption.deleted', async function () {
- await servers[0].captions.delete({ videoId: videoUUID, language: 'en' })
-
- await checkHook('action:api.video-caption.deleted')
- })
- })
-
- describe('Users hooks', function () {
- let userId: number
-
- it('Should run action:api.user.registered', async function () {
- await servers[0].registrations.register({ username: 'registered_user' })
-
- await checkHook('action:api.user.registered')
- })
-
- it('Should run action:api.user.created', async function () {
- const user = await servers[0].users.create({ username: 'created_user' })
- userId = user.id
-
- await checkHook('action:api.user.created')
- })
-
- it('Should run action:api.user.oauth2-got-token', async function () {
- await servers[0].login.login({ user: { username: 'created_user' } })
-
- await checkHook('action:api.user.oauth2-got-token')
- })
-
- it('Should run action:api.user.blocked', async function () {
- await servers[0].users.banUser({ userId })
-
- await checkHook('action:api.user.blocked')
- })
-
- it('Should run action:api.user.unblocked', async function () {
- await servers[0].users.unbanUser({ userId })
-
- await checkHook('action:api.user.unblocked')
- })
-
- it('Should run action:api.user.updated', async function () {
- await servers[0].users.update({ userId, videoQuota: 50 })
-
- await checkHook('action:api.user.updated')
- })
-
- it('Should run action:api.user.deleted', async function () {
- await servers[0].users.remove({ userId })
-
- await checkHook('action:api.user.deleted')
- })
- })
-
- describe('Playlist hooks', function () {
- let playlistId: number
- let videoId: number
-
- before(async function () {
- {
- const { id } = await servers[0].playlists.create({
- attributes: {
- displayName: 'My playlist',
- privacy: VideoPlaylistPrivacy.PRIVATE
- }
- })
- playlistId = id
- }
-
- {
- const { id } = await servers[0].videos.upload({ attributes: { name: 'my super name' } })
- videoId = id
- }
- })
-
- it('Should run action:api.video-playlist-element.created', async function () {
- await servers[0].playlists.addElement({ playlistId, attributes: { videoId } })
-
- await checkHook('action:api.video-playlist-element.created')
- })
- })
-
- describe('Notification hook', function () {
-
- it('Should run action:notifier.notification.created', async function () {
- await checkHook('action:notifier.notification.created', false)
- })
- })
-
- describe('Activity Pub hooks', function () {
- let videoUUID: string
-
- it('Should run action:activity-pub.remote-video.created', async function () {
- this.timeout(30000)
-
- const { uuid } = await servers[1].videos.quickUpload({ name: 'remote video' })
- videoUUID = uuid
-
- await servers[0].servers.waitUntilLog('action:activity-pub.remote-video.created - AP remote video - video remote video')
- })
-
- it('Should run action:activity-pub.remote-video.updated', async function () {
- this.timeout(30000)
-
- await servers[1].videos.update({ id: videoUUID, attributes: { name: 'remote video updated' } })
-
- await servers[0].servers.waitUntilLog(
- 'action:activity-pub.remote-video.updated - AP remote video updated - video remote video updated',
- 1,
- false
- )
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/plugins/external-auth.ts b/server/tests/plugins/external-auth.ts
deleted file mode 100644
index e4015939a..000000000
--- a/server/tests/plugins/external-auth.ts
+++ /dev/null
@@ -1,436 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, UserAdminFlag, UserRole } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- decodeQueryString,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-async function loginExternal (options: {
- server: PeerTubeServer
- npmName: string
- authName: string
- username: string
- query?: any
- expectedStatus?: HttpStatusCode
- expectedStatusStep2?: HttpStatusCode
-}) {
- const res = await options.server.plugins.getExternalAuth({
- npmName: options.npmName,
- npmVersion: '0.0.1',
- authName: options.authName,
- query: options.query,
- expectedStatus: options.expectedStatus || HttpStatusCode.FOUND_302
- })
-
- if (res.status !== HttpStatusCode.FOUND_302) return
-
- const location = res.header.location
- const { externalAuthToken } = decodeQueryString(location)
-
- const resLogin = await options.server.login.loginUsingExternalToken({
- username: options.username,
- externalAuthToken: externalAuthToken as string,
- expectedStatus: options.expectedStatusStep2
- })
-
- return resLogin.body
-}
-
-describe('Test external auth plugins', function () {
- let server: PeerTubeServer
-
- let cyanAccessToken: string
- let cyanRefreshToken: string
-
- let kefkaAccessToken: string
- let kefkaRefreshToken: string
- let kefkaId: number
-
- let externalAuthToken: string
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1, {
- rates_limit: {
- login: {
- max: 30
- }
- }
- })
-
- await setAccessTokensToServers([ server ])
-
- for (const suffix of [ 'one', 'two', 'three' ]) {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-external-auth-' + suffix) })
- }
- })
-
- it('Should display the correct configuration', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredExternalAuths
- expect(auths).to.have.lengthOf(9)
-
- const auth2 = auths.find((a) => a.authName === 'external-auth-2')
- expect(auth2).to.exist
- expect(auth2.authDisplayName).to.equal('External Auth 2')
- expect(auth2.npmName).to.equal('peertube-plugin-test-external-auth-one')
- })
-
- it('Should redirect for a Cyan login', async function () {
- const res = await server.plugins.getExternalAuth({
- npmName: 'test-external-auth-one',
- npmVersion: '0.0.1',
- authName: 'external-auth-1',
- query: {
- username: 'cyan'
- },
- expectedStatus: HttpStatusCode.FOUND_302
- })
-
- const location = res.header.location
- expect(location.startsWith('/login?')).to.be.true
-
- const searchParams = decodeQueryString(location)
-
- expect(searchParams.externalAuthToken).to.exist
- expect(searchParams.username).to.equal('cyan')
-
- externalAuthToken = searchParams.externalAuthToken as string
- })
-
- it('Should reject auto external login with a missing or invalid token', async function () {
- const command = server.login
-
- await command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: '', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: 'blabla', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should reject auto external login with a missing or invalid username', async function () {
- const command = server.login
-
- await command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should reject auto external login with an expired token', async function () {
- this.timeout(15000)
-
- await wait(5000)
-
- await server.login.loginUsingExternalToken({
- username: 'cyan',
- externalAuthToken,
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await server.servers.waitUntilLog('expired external auth token', 4)
- })
-
- it('Should auto login Cyan, create the user and use the token', async function () {
- {
- const res = await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-1',
- query: {
- username: 'cyan'
- },
- username: 'cyan'
- })
-
- cyanAccessToken = res.access_token
- cyanRefreshToken = res.refresh_token
- }
-
- {
- const body = await server.users.getMyInfo({ token: cyanAccessToken })
- expect(body.username).to.equal('cyan')
- expect(body.account.displayName).to.equal('cyan')
- expect(body.email).to.equal('cyan@example.com')
- expect(body.role.id).to.equal(UserRole.USER)
- expect(body.adminFlags).to.equal(UserAdminFlag.NONE)
- expect(body.videoQuota).to.equal(5242880)
- expect(body.videoQuotaDaily).to.equal(-1)
- }
- })
-
- it('Should auto login Kefka, create the user and use the token', async function () {
- {
- const res = await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-2',
- username: 'kefka'
- })
-
- kefkaAccessToken = res.access_token
- kefkaRefreshToken = res.refresh_token
- }
-
- {
- const body = await server.users.getMyInfo({ token: kefkaAccessToken })
- expect(body.username).to.equal('kefka')
- expect(body.account.displayName).to.equal('Kefka Palazzo')
- expect(body.email).to.equal('kefka@example.com')
- expect(body.role.id).to.equal(UserRole.ADMINISTRATOR)
- expect(body.adminFlags).to.equal(UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST)
- expect(body.videoQuota).to.equal(42000)
- expect(body.videoQuotaDaily).to.equal(42100)
-
- kefkaId = body.id
- }
- })
-
- it('Should refresh Cyan token, but not Kefka token', async function () {
- {
- const resRefresh = await server.login.refreshToken({ refreshToken: cyanRefreshToken })
- cyanAccessToken = resRefresh.body.access_token
- cyanRefreshToken = resRefresh.body.refresh_token
-
- const body = await server.users.getMyInfo({ token: cyanAccessToken })
- expect(body.username).to.equal('cyan')
- }
-
- {
- await server.login.refreshToken({ refreshToken: kefkaRefreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
- })
-
- it('Should update Cyan profile', async function () {
- await server.users.updateMe({
- token: cyanAccessToken,
- displayName: 'Cyan Garamonde',
- description: 'Retainer to the king of Doma'
- })
-
- const body = await server.users.getMyInfo({ token: cyanAccessToken })
- expect(body.account.displayName).to.equal('Cyan Garamonde')
- expect(body.account.description).to.equal('Retainer to the king of Doma')
- })
-
- it('Should logout Cyan', async function () {
- await server.login.logout({ token: cyanAccessToken })
- })
-
- it('Should have logged out Cyan', async function () {
- await server.servers.waitUntilLog('On logout cyan')
-
- await server.users.getMyInfo({ token: cyanAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should login Cyan and keep the old existing profile', async function () {
- {
- const res = await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-1',
- query: {
- username: 'cyan'
- },
- username: 'cyan'
- })
-
- cyanAccessToken = res.access_token
- }
-
- const body = await server.users.getMyInfo({ token: cyanAccessToken })
- expect(body.username).to.equal('cyan')
- expect(body.account.displayName).to.equal('Cyan Garamonde')
- expect(body.account.description).to.equal('Retainer to the king of Doma')
- expect(body.role.id).to.equal(UserRole.USER)
- })
-
- it('Should login Kefka and update the profile', async function () {
- {
- await server.users.update({ userId: kefkaId, videoQuota: 43000, videoQuotaDaily: 43100 })
- await server.users.updateMe({ token: kefkaAccessToken, displayName: 'kefka updated' })
-
- const body = await server.users.getMyInfo({ token: kefkaAccessToken })
- expect(body.username).to.equal('kefka')
- expect(body.account.displayName).to.equal('kefka updated')
- expect(body.videoQuota).to.equal(43000)
- expect(body.videoQuotaDaily).to.equal(43100)
- }
-
- {
- const res = await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-2',
- username: 'kefka'
- })
-
- kefkaAccessToken = res.access_token
- kefkaRefreshToken = res.refresh_token
-
- const body = await server.users.getMyInfo({ token: kefkaAccessToken })
- expect(body.username).to.equal('kefka')
- expect(body.account.displayName).to.equal('Kefka Palazzo')
- expect(body.videoQuota).to.equal(42000)
- expect(body.videoQuotaDaily).to.equal(43100)
- }
- })
-
- it('Should not update an external auth email', async function () {
- await server.users.updateMe({
- token: cyanAccessToken,
- email: 'toto@example.com',
- currentPassword: 'toto',
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should reject token of Kefka by the plugin hook', async function () {
- await wait(5000)
-
- await server.users.getMyInfo({ token: kefkaAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should unregister external-auth-2 and do not login existing Kefka', async function () {
- await server.plugins.updateSettings({
- npmName: 'peertube-plugin-test-external-auth-one',
- settings: { disableKefka: true }
- })
-
- await server.login.login({ user: { username: 'kefka', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
-
- await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-2',
- query: {
- username: 'kefka'
- },
- username: 'kefka',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should have disabled this auth', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredExternalAuths
- expect(auths).to.have.lengthOf(8)
-
- const auth1 = auths.find(a => a.authName === 'external-auth-2')
- expect(auth1).to.not.exist
- })
-
- it('Should uninstall the plugin one and do not login Cyan', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-external-auth-one' })
-
- await loginExternal({
- server,
- npmName: 'test-external-auth-one',
- authName: 'external-auth-1',
- query: {
- username: 'cyan'
- },
- username: 'cyan',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
-
- await server.login.login({ user: { username: 'cyan', password: null }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.login.login({ user: { username: 'cyan', password: '' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.login.login({ user: { username: 'cyan', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not login kefka with another plugin', async function () {
- await loginExternal({
- server,
- npmName: 'test-external-auth-two',
- authName: 'external-auth-4',
- username: 'kefka2',
- expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
- })
-
- await loginExternal({
- server,
- npmName: 'test-external-auth-two',
- authName: 'external-auth-4',
- username: 'kefka',
- expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should not login an existing user email', async function () {
- await server.users.create({ username: 'existing_user', password: 'super_password' })
-
- await loginExternal({
- server,
- npmName: 'test-external-auth-two',
- authName: 'external-auth-6',
- username: 'existing_user',
- expectedStatusStep2: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should be able to login an existing user username and channel', async function () {
- await server.users.create({ username: 'existing_user2' })
- await server.users.create({ username: 'existing_user2-1_channel' })
-
- // Test twice to ensure we don't generate a username on every login
- for (let i = 0; i < 2; i++) {
- const res = await loginExternal({
- server,
- npmName: 'test-external-auth-two',
- authName: 'external-auth-7',
- username: 'existing_user2'
- })
-
- const token = res.access_token
-
- const myInfo = await server.users.getMyInfo({ token })
- expect(myInfo.username).to.equal('existing_user2-1')
-
- expect(myInfo.videoChannels[0].name).to.equal('existing_user2-1_channel-1')
- }
- })
-
- it('Should display the correct configuration', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredExternalAuths
- expect(auths).to.have.lengthOf(7)
-
- const auth2 = auths.find((a) => a.authName === 'external-auth-2')
- expect(auth2).to.not.exist
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-
- it('Should forward the redirectUrl if the plugin returns one', async function () {
- const resLogin = await loginExternal({
- server,
- npmName: 'test-external-auth-three',
- authName: 'external-auth-7',
- username: 'cid'
- })
-
- const { redirectUrl } = await server.login.logout({ token: resLogin.access_token })
- expect(redirectUrl).to.equal('https://example.com/redirectUrl')
- })
-
- it('Should call the plugin\'s onLogout method with the request', async function () {
- const resLogin = await loginExternal({
- server,
- npmName: 'test-external-auth-three',
- authName: 'external-auth-8',
- username: 'cid'
- })
-
- const { redirectUrl } = await server.login.logout({ token: resLogin.access_token })
- expect(redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token)
- })
-})
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
deleted file mode 100644
index 8382b400f..000000000
--- a/server/tests/plugins/filter-hooks.ts
+++ /dev/null
@@ -1,909 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- HttpStatusCode,
- PeerTubeProblemDocument,
- VideoDetails,
- VideoImportState,
- VideoPlaylist,
- VideoPlaylistPrivacy,
- VideoPrivacy
-} from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeActivityPubGetRequest,
- makeGetRequest,
- makeRawRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs
-} from '@shared/server-commands'
-import { FIXTURE_URLS } from '../shared'
-
-describe('Test plugin filter hooks', function () {
- let servers: PeerTubeServer[]
- let videoUUID: string
- let threadId: number
- let videoPlaylistUUID: string
-
- before(async function () {
- this.timeout(120000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath() })
- await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
- {
- ({ uuid: videoPlaylistUUID } = await servers[0].playlists.create({
- attributes: {
- displayName: 'my super playlist',
- privacy: VideoPlaylistPrivacy.PUBLIC,
- description: 'my super description',
- videoChannelId: servers[0].store.channel.id
- }
- }))
- }
-
- for (let i = 0; i < 10; i++) {
- const video = await servers[0].videos.upload({ attributes: { name: 'default video ' + i } })
- await servers[0].playlists.addElement({ playlistId: videoPlaylistUUID, attributes: { videoId: video.id } })
- }
-
- const { data } = await servers[0].videos.list()
- videoUUID = data[0].uuid
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: { enabled: true },
- signup: { enabled: true },
- videoFile: {
- update: {
- enabled: true
- }
- },
- import: {
- videos: {
- http: { enabled: true },
- torrent: { enabled: true }
- }
- }
- }
- })
-
- // Root subscribes to itself
- await servers[0].subscriptions.add({ targetUri: 'root_channel@' + servers[0].host })
- })
-
- describe('Videos', function () {
-
- it('Should run filter:api.videos.list.params', async function () {
- const { data } = await servers[0].videos.list({ start: 0, count: 2 })
-
- // 2 plugins do +1 to the count parameter
- expect(data).to.have.lengthOf(4)
- })
-
- it('Should run filter:api.videos.list.result', async function () {
- const { total } = await servers[0].videos.list({ start: 0, count: 0 })
-
- // Plugin do +1 to the total result
- expect(total).to.equal(11)
- })
-
- it('Should run filter:api.video-playlist.videos.list.params', async function () {
- const { data } = await servers[0].playlists.listVideos({
- count: 2,
- playlistId: videoPlaylistUUID
- })
-
- // 1 plugin do +1 to the count parameter
- expect(data).to.have.lengthOf(3)
- })
-
- it('Should run filter:api.video-playlist.videos.list.result', async function () {
- const { total } = await servers[0].playlists.listVideos({
- count: 0,
- playlistId: videoPlaylistUUID
- })
-
- // Plugin do +1 to the total result
- expect(total).to.equal(11)
- })
-
- it('Should run filter:api.accounts.videos.list.params', async function () {
- const { data } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
-
- // 1 plugin do +1 to the count parameter
- expect(data).to.have.lengthOf(3)
- })
-
- it('Should run filter:api.accounts.videos.list.result', async function () {
- const { total } = await servers[0].videos.listByAccount({ handle: 'root', start: 0, count: 2 })
-
- // Plugin do +2 to the total result
- expect(total).to.equal(12)
- })
-
- it('Should run filter:api.video-channels.videos.list.params', async function () {
- const { data } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
-
- // 1 plugin do +3 to the count parameter
- expect(data).to.have.lengthOf(5)
- })
-
- it('Should run filter:api.video-channels.videos.list.result', async function () {
- const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', start: 0, count: 2 })
-
- // Plugin do +3 to the total result
- expect(total).to.equal(13)
- })
-
- it('Should run filter:api.user.me.videos.list.params', async function () {
- const { data } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
-
- // 1 plugin do +4 to the count parameter
- expect(data).to.have.lengthOf(6)
- })
-
- it('Should run filter:api.user.me.videos.list.result', async function () {
- const { total } = await servers[0].videos.listMyVideos({ start: 0, count: 2 })
-
- // Plugin do +4 to the total result
- expect(total).to.equal(14)
- })
-
- it('Should run filter:api.user.me.subscription-videos.list.params', async function () {
- const { data } = await servers[0].videos.listMySubscriptionVideos({ start: 0, count: 2 })
-
- // 1 plugin do +1 to the count parameter
- expect(data).to.have.lengthOf(3)
- })
-
- it('Should run filter:api.user.me.subscription-videos.list.result', async function () {
- const { total } = await servers[0].videos.listMySubscriptionVideos({ start: 0, count: 2 })
-
- // Plugin do +4 to the total result
- expect(total).to.equal(14)
- })
-
- it('Should run filter:api.video.get.result', async function () {
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.name).to.contain('<3')
- })
- })
-
- describe('Video/live/import accept', function () {
-
- it('Should run filter:api.video.upload.accept.result', async function () {
- const options = { attributes: { name: 'video with bad word' }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }
- await servers[0].videos.upload({ mode: 'legacy', ...options })
- await servers[0].videos.upload({ mode: 'resumable', ...options })
- })
-
- it('Should run filter:api.video.update-file.accept.result', async function () {
- const res = await servers[0].videos.replaceSourceFile({
- videoId: videoUUID,
- fixture: 'video_short1.webm',
- completedExpectedStatus: HttpStatusCode.FORBIDDEN_403
- })
-
- expect((res as any)?.error).to.equal('no webm')
- })
-
- it('Should run filter:api.live-video.create.accept.result', async function () {
- const attributes = {
- name: 'video with bad word',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id
- }
-
- await servers[0].live.create({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should run filter:api.video.pre-import-url.accept.result', async function () {
- const attributes = {
- name: 'normal title',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id,
- targetUrl: FIXTURE_URLS.goodVideo + 'bad'
- }
- await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
- const attributes = {
- name: 'bad torrent',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id,
- torrentfile: 'video-720p.torrent' as any
- }
- await servers[0].imports.importVideo({ attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- })
-
- it('Should run filter:api.video.post-import-url.accept.result', async function () {
- this.timeout(60000)
-
- let videoImportId: number
-
- {
- const attributes = {
- name: 'title with bad word',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id,
- targetUrl: FIXTURE_URLS.goodVideo
- }
- const body = await servers[0].imports.importVideo({ attributes })
- videoImportId = body.id
- }
-
- await waitJobs(servers)
-
- {
- const body = await servers[0].imports.getMyVideoImports()
- const videoImports = body.data
-
- const videoImport = videoImports.find(i => i.id === videoImportId)
-
- expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
- expect(videoImport.state.label).to.equal('Rejected')
- }
- })
-
- it('Should run filter:api.video.post-import-torrent.accept.result', async function () {
- this.timeout(60000)
-
- let videoImportId: number
-
- {
- const attributes = {
- name: 'title with bad word',
- privacy: VideoPrivacy.PUBLIC,
- channelId: servers[0].store.channel.id,
- torrentfile: 'video-720p.torrent' as any
- }
- const body = await servers[0].imports.importVideo({ attributes })
- videoImportId = body.id
- }
-
- await waitJobs(servers)
-
- {
- const { data: videoImports } = await servers[0].imports.getMyVideoImports()
-
- const videoImport = videoImports.find(i => i.id === videoImportId)
-
- expect(videoImport.state.id).to.equal(VideoImportState.REJECTED)
- expect(videoImport.state.label).to.equal('Rejected')
- }
- })
- })
-
- describe('Video comments accept', function () {
-
- it('Should run filter:api.video-thread.create.accept.result', async function () {
- await servers[0].comments.createThread({
- videoId: videoUUID,
- text: 'comment with bad word',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- })
-
- it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
- const created = await servers[0].comments.createThread({ videoId: videoUUID, text: 'thread' })
- threadId = created.id
-
- await servers[0].comments.addReply({
- videoId: videoUUID,
- toCommentId: threadId,
- text: 'comment with bad word',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
- await servers[0].comments.addReply({
- videoId: videoUUID,
- toCommentId: threadId,
- text: 'comment with good word',
- expectedStatus: HttpStatusCode.OK_200
- })
- })
-
- it('Should run filter:activity-pub.remote-video-comment.create.accept.result on a thread creation', async function () {
- this.timeout(30000)
-
- await servers[1].comments.createThread({ videoId: videoUUID, text: 'comment with bad word' })
-
- await waitJobs(servers)
-
- {
- const thread = await servers[0].comments.listThreads({ videoId: videoUUID })
- expect(thread.data).to.have.lengthOf(1)
- expect(thread.data[0].text).to.not.include(' bad ')
- }
-
- {
- const thread = await servers[1].comments.listThreads({ videoId: videoUUID })
- expect(thread.data).to.have.lengthOf(2)
- }
- })
-
- it('Should run filter:activity-pub.remote-video-comment.create.accept.result on a reply creation', async function () {
- this.timeout(30000)
-
- const { data } = await servers[1].comments.listThreads({ videoId: videoUUID })
- const threadIdServer2 = data.find(t => t.text === 'thread').id
-
- await servers[1].comments.addReply({
- videoId: videoUUID,
- toCommentId: threadIdServer2,
- text: 'comment with bad word'
- })
-
- await waitJobs(servers)
-
- {
- const tree = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
- expect(tree.children).to.have.lengthOf(1)
- expect(tree.children[0].comment.text).to.not.include(' bad ')
- }
-
- {
- const tree = await servers[1].comments.getThread({ videoId: videoUUID, threadId: threadIdServer2 })
- expect(tree.children).to.have.lengthOf(2)
- }
- })
- })
-
- describe('Video comments', function () {
-
- it('Should run filter:api.video-threads.list.params', async function () {
- const { data } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
-
- // our plugin do +1 to the count parameter
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should run filter:api.video-threads.list.result', async function () {
- const { total } = await servers[0].comments.listThreads({ videoId: videoUUID, start: 0, count: 0 })
-
- // Plugin do +1 to the total result
- expect(total).to.equal(2)
- })
-
- it('Should run filter:api.video-thread-comments.list.params')
-
- it('Should run filter:api.video-thread-comments.list.result', async function () {
- const thread = await servers[0].comments.getThread({ videoId: videoUUID, threadId })
-
- expect(thread.comment.text.endsWith(' <3')).to.be.true
- })
-
- it('Should run filter:api.overviews.videos.list.{params,result}', async function () {
- await servers[0].overviews.getVideos({ page: 1 })
-
- // 3 because we get 3 samples per page
- await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.params', 3)
- await servers[0].servers.waitUntilLog('Run hook filter:api.overviews.videos.list.result', 3)
- })
- })
-
- describe('filter:video.auto-blacklist.result', function () {
-
- async function checkIsBlacklisted (id: number | string, value: boolean) {
- const video = await servers[0].videos.getWithToken({ id })
- expect(video.blacklisted).to.equal(value)
- }
-
- it('Should blacklist on upload', async function () {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video please blacklist me' } })
- await checkIsBlacklisted(uuid, true)
- })
-
- it('Should blacklist on import', async function () {
- this.timeout(15000)
-
- const attributes = {
- name: 'video please blacklist me',
- targetUrl: FIXTURE_URLS.goodVideo,
- channelId: servers[0].store.channel.id
- }
- const body = await servers[0].imports.importVideo({ attributes })
- await checkIsBlacklisted(body.video.uuid, true)
- })
-
- it('Should blacklist on update', async function () {
- const { uuid } = await servers[0].videos.upload({ attributes: { name: 'video' } })
- await checkIsBlacklisted(uuid, false)
-
- await servers[0].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
- await checkIsBlacklisted(uuid, true)
- })
-
- it('Should blacklist on remote upload', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'remote please blacklist me' } })
- await waitJobs(servers)
-
- await checkIsBlacklisted(uuid, true)
- })
-
- it('Should blacklist on remote update', async function () {
- this.timeout(120000)
-
- const { uuid } = await servers[1].videos.upload({ attributes: { name: 'video' } })
- await waitJobs(servers)
-
- await checkIsBlacklisted(uuid, false)
-
- await servers[1].videos.update({ id: uuid, attributes: { name: 'please blacklist me' } })
- await waitJobs(servers)
-
- await checkIsBlacklisted(uuid, true)
- })
- })
-
- describe('Should run filter:api.user.signup.allowed.result', function () {
-
- before(async function () {
- await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: false } } })
- })
-
- it('Should run on config endpoint', async function () {
- const body = await servers[0].config.getConfig()
- expect(body.signup.allowed).to.be.true
- })
-
- it('Should allow a signup', async function () {
- await servers[0].registrations.register({ username: 'john1' })
- })
-
- it('Should not allow a signup', async function () {
- const res = await servers[0].registrations.register({
- username: 'jma 1',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
-
- expect(res.body.error).to.equal('No jma 1')
- })
- })
-
- describe('Should run filter:api.user.request-signup.allowed.result', function () {
-
- before(async function () {
- await servers[0].config.updateExistingSubConfig({ newConfig: { signup: { requiresApproval: true } } })
- })
-
- it('Should run on config endpoint', async function () {
- const body = await servers[0].config.getConfig()
- expect(body.signup.allowed).to.be.true
- })
-
- it('Should allow a signup request', async function () {
- await servers[0].registrations.requestRegistration({ username: 'john2', registrationReason: 'tt' })
- })
-
- it('Should not allow a signup request', async function () {
- const body = await servers[0].registrations.requestRegistration({
- username: 'jma 2',
- registrationReason: 'tt',
- expectedStatus: HttpStatusCode.FORBIDDEN_403
- })
-
- expect((body as unknown as PeerTubeProblemDocument).error).to.equal('No jma 2')
- })
- })
-
- describe('Download hooks', function () {
- const downloadVideos: VideoDetails[] = []
- let downloadVideo2Token: string
-
- before(async function () {
- this.timeout(120000)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- webVideos: {
- enabled: true
- },
- hls: {
- enabled: true
- }
- }
- }
- })
-
- const uuids: string[] = []
-
- for (const name of [ 'bad torrent', 'bad file', 'bad playlist file' ]) {
- const uuid = (await servers[0].videos.quickUpload({ name })).uuid
- uuids.push(uuid)
- }
-
- await waitJobs(servers)
-
- for (const uuid of uuids) {
- downloadVideos.push(await servers[0].videos.get({ id: uuid }))
- }
-
- downloadVideo2Token = await servers[0].videoToken.getVideoFileToken({ videoId: downloadVideos[2].uuid })
- })
-
- it('Should run filter:api.download.torrent.allowed.result', async function () {
- const res = await makeRawRequest({ url: downloadVideos[0].files[0].torrentDownloadUrl, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- expect(res.body.error).to.equal('Liu Bei')
-
- await makeRawRequest({ url: downloadVideos[1].files[0].torrentDownloadUrl, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: downloadVideos[2].files[0].torrentDownloadUrl, expectedStatus: HttpStatusCode.OK_200 })
- })
-
- it('Should run filter:api.download.video.allowed.result', async function () {
- {
- const refused = downloadVideos[1].files[0].fileDownloadUrl
- const allowed = [
- downloadVideos[0].files[0].fileDownloadUrl,
- downloadVideos[2].files[0].fileDownloadUrl
- ]
-
- const res = await makeRawRequest({ url: refused, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- expect(res.body.error).to.equal('Cao Cao')
-
- for (const url of allowed) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- {
- const refused = downloadVideos[2].streamingPlaylists[0].files[0].fileDownloadUrl
-
- const allowed = [
- downloadVideos[2].files[0].fileDownloadUrl,
- downloadVideos[0].streamingPlaylists[0].files[0].fileDownloadUrl,
- downloadVideos[1].streamingPlaylists[0].files[0].fileDownloadUrl
- ]
-
- // Only streaming playlist is refuse
- const res = await makeRawRequest({ url: refused, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
- expect(res.body.error).to.equal('Sun Jian')
-
- // But not we there is a user in res
- await makeRawRequest({ url: refused, token: servers[0].accessToken, expectedStatus: HttpStatusCode.OK_200 })
- await makeRawRequest({ url: refused, query: { videoFileToken: downloadVideo2Token }, expectedStatus: HttpStatusCode.OK_200 })
-
- // Other files work
- for (const url of allowed) {
- await makeRawRequest({ url, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
- })
- })
-
- describe('Embed filters', function () {
- const embedVideos: VideoDetails[] = []
- const embedPlaylists: VideoPlaylist[] = []
-
- before(async function () {
- this.timeout(60000)
-
- await servers[0].config.disableTranscoding()
-
- for (const name of [ 'bad embed', 'good embed' ]) {
- {
- const uuid = (await servers[0].videos.quickUpload({ name })).uuid
- embedVideos.push(await servers[0].videos.get({ id: uuid }))
- }
-
- {
- const attributes = { displayName: name, videoChannelId: servers[0].store.channel.id, privacy: VideoPlaylistPrivacy.PUBLIC }
- const { id } = await servers[0].playlists.create({ attributes })
-
- const playlist = await servers[0].playlists.get({ playlistId: id })
- embedPlaylists.push(playlist)
- }
- }
- })
-
- it('Should run filter:html.embed.video.allowed.result', async function () {
- const res = await makeGetRequest({ url: servers[0].url, path: embedVideos[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).to.equal('Lu Bu')
- })
-
- it('Should run filter:html.embed.video-playlist.allowed.result', async function () {
- const res = await makeGetRequest({ url: servers[0].url, path: embedPlaylists[0].embedPath, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).to.equal('Diao Chan')
- })
- })
-
- describe('Client HTML filters', function () {
- let videoUUID: string
-
- before(async function () {
- this.timeout(60000)
-
- const { uuid } = await servers[0].videos.quickUpload({ name: 'html video' })
- videoUUID = uuid
- })
-
- it('Should run filter:html.client.json-ld.result', async function () {
- const res = await makeGetRequest({ url: servers[0].url, path: '/w/' + videoUUID, expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).to.contain('"recordedAt":"http://example.com/recordedAt"')
- })
-
- it('Should not run filter:html.client.json-ld.result with an account', async function () {
- const res = await makeGetRequest({ url: servers[0].url, path: '/a/root', expectedStatus: HttpStatusCode.OK_200 })
- expect(res.text).not.to.contain('"recordedAt":"http://example.com/recordedAt"')
- })
- })
-
- describe('Search filters', function () {
-
- before(async function () {
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- search: {
- searchIndex: {
- enabled: true,
- isDefaultSearch: false,
- disableLocalSearch: false
- }
- }
- }
- })
- })
-
- it('Should run filter:api.search.videos.local.list.{params,result}', async function () {
- await servers[0].search.advancedVideoSearch({
- search: {
- search: 'Sun Quan'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
- })
-
- it('Should run filter:api.search.videos.index.list.{params,result}', async function () {
- await servers[0].search.advancedVideoSearch({
- search: {
- search: 'Sun Quan',
- searchTarget: 'search-index'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.local.list.result', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.videos.index.list.result', 1)
- })
-
- it('Should run filter:api.search.video-channels.local.list.{params,result}', async function () {
- await servers[0].search.advancedChannelSearch({
- search: {
- search: 'Sun Ce'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
- })
-
- it('Should run filter:api.search.video-channels.index.list.{params,result}', async function () {
- await servers[0].search.advancedChannelSearch({
- search: {
- search: 'Sun Ce',
- searchTarget: 'search-index'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.local.list.result', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-channels.index.list.result', 1)
- })
-
- it('Should run filter:api.search.video-playlists.local.list.{params,result}', async function () {
- await servers[0].search.advancedPlaylistSearch({
- search: {
- search: 'Sun Jian'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
- })
-
- it('Should run filter:api.search.video-playlists.index.list.{params,result}', async function () {
- await servers[0].search.advancedPlaylistSearch({
- search: {
- search: 'Sun Jian',
- searchTarget: 'search-index'
- }
- })
-
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.local.list.result', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.params', 1)
- await servers[0].servers.waitUntilLog('Run hook filter:api.search.video-playlists.index.list.result', 1)
- })
- })
-
- describe('Upload/import/live attributes filters', function () {
-
- before(async function () {
- await servers[0].config.enableLive({ transcoding: false, allowReplay: false })
- await servers[0].config.enableImports()
- await servers[0].config.disableTranscoding()
- })
-
- it('Should run filter:api.video.upload.video-attribute.result', async function () {
- for (const mode of [ 'legacy' as 'legacy', 'resumable' as 'resumable' ]) {
- const { id } = await servers[0].videos.upload({ attributes: { name: 'video', description: 'upload' }, mode })
-
- const video = await servers[0].videos.get({ id })
- expect(video.description).to.equal('upload - filter:api.video.upload.video-attribute.result')
- }
- })
-
- it('Should run filter:api.video.import-url.video-attribute.result', async function () {
- const attributes = {
- name: 'video',
- description: 'import url',
- channelId: servers[0].store.channel.id,
- targetUrl: FIXTURE_URLS.goodVideo,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video: { id } } = await servers[0].imports.importVideo({ attributes })
-
- const video = await servers[0].videos.get({ id })
- expect(video.description).to.equal('import url - filter:api.video.import-url.video-attribute.result')
- })
-
- it('Should run filter:api.video.import-torrent.video-attribute.result', async function () {
- const attributes = {
- name: 'video',
- description: 'import torrent',
- channelId: servers[0].store.channel.id,
- magnetUri: FIXTURE_URLS.magnet,
- privacy: VideoPrivacy.PUBLIC
- }
- const { video: { id } } = await servers[0].imports.importVideo({ attributes })
-
- const video = await servers[0].videos.get({ id })
- expect(video.description).to.equal('import torrent - filter:api.video.import-torrent.video-attribute.result')
- })
-
- it('Should run filter:api.video.live.video-attribute.result', async function () {
- const fields = {
- name: 'live',
- description: 'live',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
- const { id } = await servers[0].live.create({ fields })
-
- const video = await servers[0].videos.get({ id })
- expect(video.description).to.equal('live - filter:api.video.live.video-attribute.result')
- })
- })
-
- describe('Stats filters', function () {
-
- it('Should run filter:api.server.stats.get.result', async function () {
- const data = await servers[0].stats.get()
-
- expect((data as any).customStats).to.equal(14)
- })
-
- })
-
- describe('Job queue filters', function () {
- let videoUUID: string
-
- before(async function () {
- this.timeout(120_000)
-
- await servers[0].config.enableMinimumTranscoding()
- const { uuid } = await servers[0].videos.quickUpload({ name: 'studio' })
-
- const video = await servers[0].videos.get({ id: uuid })
- expect(video.duration).at.least(2)
- videoUUID = video.uuid
-
- await waitJobs(servers)
-
- await servers[0].config.enableStudio()
- })
-
- it('Should run filter:job-queue.process.params', async function () {
- this.timeout(120_000)
-
- await servers[0].videoStudio.createEditionTasks({
- videoId: videoUUID,
- tasks: [
- {
- name: 'add-intro',
- options: {
- file: 'video_very_short_240p.mp4'
- }
- }
- ]
- })
-
- await waitJobs(servers)
-
- await servers[0].servers.waitUntilLog('Run hook filter:job-queue.process.params', 1, false)
-
- const video = await servers[0].videos.get({ id: videoUUID })
- expect(video.duration).at.most(2)
- })
-
- it('Should run filter:job-queue.process.result', async function () {
- await servers[0].servers.waitUntilLog('Run hook filter:job-queue.process.result', 1, false)
- })
- })
-
- describe('Transcoding filters', async function () {
-
- it('Should run filter:transcoding.auto.resolutions-to-transcode.result', async function () {
- const { uuid } = await servers[0].videos.quickUpload({ name: 'transcode-filter' })
-
- await waitJobs(servers)
-
- const video = await servers[0].videos.get({ id: uuid })
- expect(video.files).to.have.lengthOf(2)
- expect(video.files.find(f => f.resolution.id === 100 as any)).to.exist
- })
- })
-
- describe('Video channel filters', async function () {
-
- it('Should run filter:api.video-channels.list.params', async function () {
- const { data } = await servers[0].channels.list({ start: 0, count: 0 })
-
- // plugin do +1 to the count parameter
- expect(data).to.have.lengthOf(1)
- })
-
- it('Should run filter:api.video-channels.list.result', async function () {
- const { total } = await servers[0].channels.list({ start: 0, count: 1 })
-
- // plugin do +1 to the total parameter
- expect(total).to.equal(4)
- })
-
- it('Should run filter:api.video-channel.get.result', async function () {
- const channel = await servers[0].channels.get({ channelName: 'root_channel' })
- expect(channel.displayName).to.equal('Main root channel <3')
- })
- })
-
- describe('Activity Pub', function () {
-
- it('Should run filter:activity-pub.activity.context.build.result', async function () {
- const { body } = await makeActivityPubGetRequest(servers[0].url, '/w/' + videoUUID)
- expect(body.type).to.equal('Video')
-
- expect(body['@context'].some(c => {
- return typeof c === 'object' && c.recordedAt === 'https://schema.org/recordedAt'
- })).to.be.true
- })
-
- it('Should run filter:activity-pub.video.json-ld.build.result', async function () {
- const { body } = await makeActivityPubGetRequest(servers[0].url, '/w/' + videoUUID)
- expect(body.name).to.equal('default video 0')
- expect(body.videoName).to.equal('default video 0')
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/plugins/html-injection.ts b/server/tests/plugins/html-injection.ts
deleted file mode 100644
index fe16bf1e6..000000000
--- a/server/tests/plugins/html-injection.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- makeHTMLRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-
-describe('Test plugins HTML injection', function () {
- let server: PeerTubeServer = null
- let command: PluginsCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- command = server.plugins
- })
-
- it('Should not inject global css file in HTML', async function () {
- {
- const text = await command.getCSS()
- expect(text).to.be.empty
- }
-
- for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
- const res = await makeHTMLRequest(server.url, path)
- expect(res.text).to.not.include('link rel="stylesheet" href="/plugins/global.css')
- }
- })
-
- it('Should install a plugin and a theme', async function () {
- this.timeout(30000)
-
- await command.install({ npmName: 'peertube-plugin-hello-world' })
- })
-
- it('Should have the correct global css', async function () {
- {
- const text = await command.getCSS()
- expect(text).to.contain('background-color: red')
- }
-
- for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
- const res = await makeHTMLRequest(server.url, path)
- expect(res.text).to.include('link rel="stylesheet" href="/plugins/global.css')
- }
- })
-
- it('Should have an empty global css on uninstall', async function () {
- await command.uninstall({ npmName: 'peertube-plugin-hello-world' })
-
- {
- const text = await command.getCSS()
- expect(text).to.be.empty
- }
-
- for (const path of [ '/', '/videos/embed/1', '/video-playlists/embed/1' ]) {
- const res = await makeHTMLRequest(server.url, path)
- expect(res.text).to.not.include('link rel="stylesheet" href="/plugins/global.css')
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/id-and-pass-auth.ts b/server/tests/plugins/id-and-pass-auth.ts
deleted file mode 100644
index 127c29cbc..000000000
--- a/server/tests/plugins/id-and-pass-auth.ts
+++ /dev/null
@@ -1,242 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { wait } from '@shared/core-utils'
-import { HttpStatusCode, UserRole } from '@shared/models'
-import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test id and pass auth plugins', function () {
- let server: PeerTubeServer
-
- let crashAccessToken: string
- let crashRefreshToken: string
-
- let lagunaAccessToken: string
- let lagunaRefreshToken: string
- let lagunaId: number
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- for (const suffix of [ 'one', 'two', 'three' ]) {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-id-pass-auth-' + suffix) })
- }
- })
-
- it('Should display the correct configuration', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredIdAndPassAuths
- expect(auths).to.have.lengthOf(8)
-
- const crashAuth = auths.find(a => a.authName === 'crash-auth')
- expect(crashAuth).to.exist
- expect(crashAuth.npmName).to.equal('peertube-plugin-test-id-pass-auth-one')
- expect(crashAuth.weight).to.equal(50)
- })
-
- it('Should not login', async function () {
- await server.login.login({ user: { username: 'toto', password: 'password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should login Spyro, create the user and use the token', async function () {
- const accessToken = await server.login.getAccessToken({ username: 'spyro', password: 'spyro password' })
-
- const body = await server.users.getMyInfo({ token: accessToken })
-
- expect(body.username).to.equal('spyro')
- expect(body.account.displayName).to.equal('Spyro the Dragon')
- expect(body.role.id).to.equal(UserRole.USER)
- })
-
- it('Should login Crash, create the user and use the token', async function () {
- {
- const body = await server.login.login({ user: { username: 'crash', password: 'crash password' } })
- crashAccessToken = body.access_token
- crashRefreshToken = body.refresh_token
- }
-
- {
- const body = await server.users.getMyInfo({ token: crashAccessToken })
-
- expect(body.username).to.equal('crash')
- expect(body.account.displayName).to.equal('Crash Bandicoot')
- expect(body.role.id).to.equal(UserRole.MODERATOR)
- }
- })
-
- it('Should login the first Laguna, create the user and use the token', async function () {
- {
- const body = await server.login.login({ user: { username: 'laguna', password: 'laguna password' } })
- lagunaAccessToken = body.access_token
- lagunaRefreshToken = body.refresh_token
- }
-
- {
- const body = await server.users.getMyInfo({ token: lagunaAccessToken })
-
- expect(body.username).to.equal('laguna')
- expect(body.account.displayName).to.equal('Laguna Loire')
- expect(body.role.id).to.equal(UserRole.USER)
-
- lagunaId = body.id
- }
- })
-
- it('Should refresh crash token, but not laguna token', async function () {
- {
- const resRefresh = await server.login.refreshToken({ refreshToken: crashRefreshToken })
- crashAccessToken = resRefresh.body.access_token
- crashRefreshToken = resRefresh.body.refresh_token
-
- const body = await server.users.getMyInfo({ token: crashAccessToken })
- expect(body.username).to.equal('crash')
- }
-
- {
- await server.login.refreshToken({ refreshToken: lagunaRefreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- }
- })
-
- it('Should update Crash profile', async function () {
- await server.users.updateMe({
- token: crashAccessToken,
- displayName: 'Beautiful Crash',
- description: 'Mutant eastern barred bandicoot'
- })
-
- const body = await server.users.getMyInfo({ token: crashAccessToken })
-
- expect(body.account.displayName).to.equal('Beautiful Crash')
- expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
- })
-
- it('Should logout Crash', async function () {
- await server.login.logout({ token: crashAccessToken })
- })
-
- it('Should have logged out Crash', async function () {
- await server.servers.waitUntilLog('On logout for auth 1 - 2')
-
- await server.users.getMyInfo({ token: crashAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should login Crash and keep the old existing profile', async function () {
- crashAccessToken = await server.login.getAccessToken({ username: 'crash', password: 'crash password' })
-
- const body = await server.users.getMyInfo({ token: crashAccessToken })
-
- expect(body.username).to.equal('crash')
- expect(body.account.displayName).to.equal('Beautiful Crash')
- expect(body.account.description).to.equal('Mutant eastern barred bandicoot')
- expect(body.role.id).to.equal(UserRole.MODERATOR)
- })
-
- it('Should login Laguna and update the profile', async function () {
- {
- await server.users.update({ userId: lagunaId, videoQuota: 43000, videoQuotaDaily: 43100 })
- await server.users.updateMe({ token: lagunaAccessToken, displayName: 'laguna updated' })
-
- const body = await server.users.getMyInfo({ token: lagunaAccessToken })
- expect(body.username).to.equal('laguna')
- expect(body.account.displayName).to.equal('laguna updated')
- expect(body.videoQuota).to.equal(43000)
- expect(body.videoQuotaDaily).to.equal(43100)
- }
-
- {
- const body = await server.login.login({ user: { username: 'laguna', password: 'laguna password' } })
- lagunaAccessToken = body.access_token
- lagunaRefreshToken = body.refresh_token
- }
-
- {
- const body = await server.users.getMyInfo({ token: lagunaAccessToken })
- expect(body.username).to.equal('laguna')
- expect(body.account.displayName).to.equal('Laguna Loire')
- expect(body.videoQuota).to.equal(42000)
- expect(body.videoQuotaDaily).to.equal(43100)
- }
- })
-
- it('Should reject token of laguna by the plugin hook', async function () {
- await wait(5000)
-
- await server.users.getMyInfo({ token: lagunaAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
- })
-
- it('Should reject an invalid username, email, role or display name', async function () {
- const command = server.login
-
- await command.login({ user: { username: 'ward', password: 'ward password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.servers.waitUntilLog('valid username')
-
- await command.login({ user: { username: 'kiros', password: 'kiros password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.servers.waitUntilLog('valid displayName')
-
- await command.login({ user: { username: 'raine', password: 'raine password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.servers.waitUntilLog('valid role')
-
- await command.login({ user: { username: 'ellone', password: 'elonne password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await server.servers.waitUntilLog('valid email')
- })
-
- it('Should unregister spyro-auth and do not login existing Spyro', async function () {
- await server.plugins.updateSettings({
- npmName: 'peertube-plugin-test-id-pass-auth-one',
- settings: { disableSpyro: true }
- })
-
- const command = server.login
- await command.login({ user: { username: 'spyro', password: 'spyro password' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- await command.login({ user: { username: 'spyro', password: 'fake' }, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should have disabled this auth', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredIdAndPassAuths
- expect(auths).to.have.lengthOf(7)
-
- const spyroAuth = auths.find(a => a.authName === 'spyro-auth')
- expect(spyroAuth).to.not.exist
- })
-
- it('Should uninstall the plugin one and do not login existing Crash', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-id-pass-auth-one' })
-
- await server.login.login({
- user: { username: 'crash', password: 'crash password' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
- })
-
- it('Should display the correct configuration', async function () {
- const config = await server.config.getConfig()
-
- const auths = config.plugin.registeredIdAndPassAuths
- expect(auths).to.have.lengthOf(6)
-
- const crashAuth = auths.find(a => a.authName === 'crash-auth')
- expect(crashAuth).to.not.exist
- })
-
- it('Should display plugin auth information in users list', async function () {
- const { data } = await server.users.list()
-
- const root = data.find(u => u.username === 'root')
- const crash = data.find(u => u.username === 'crash')
- const laguna = data.find(u => u.username === 'laguna')
-
- expect(root.pluginAuth).to.be.null
- expect(crash.pluginAuth).to.equal('peertube-plugin-test-id-pass-auth-one')
- expect(laguna.pluginAuth).to.equal('peertube-plugin-test-id-pass-auth-two')
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/index.ts b/server/tests/plugins/index.ts
deleted file mode 100644
index 210af7236..000000000
--- a/server/tests/plugins/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import './action-hooks'
-import './external-auth'
-import './filter-hooks'
-import './html-injection'
-import './id-and-pass-auth'
-import './plugin-helpers'
-import './plugin-router'
-import './plugin-storage'
-import './plugin-transcoding'
-import './plugin-unloading'
-import './plugin-websocket'
-import './translations'
-import './video-constants'
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
deleted file mode 100644
index f5a0cbe85..000000000
--- a/server/tests/plugins/plugin-helpers.ts
+++ /dev/null
@@ -1,383 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists } from 'fs-extra'
-import { HttpStatusCode, ThumbnailType } from '@shared/models'
-import {
- cleanupTests,
- createMultipleServers,
- doubleFollow,
- makeGetRequest,
- makePostBodyRequest,
- makeRawRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers,
- waitJobs
-} from '@shared/server-commands'
-import { checkVideoFilesWereRemoved } from '../shared'
-
-function postCommand (server: PeerTubeServer, command: string, bodyArg?: object) {
- const body = { command }
- if (bodyArg) Object.assign(body, bodyArg)
-
- return makePostBodyRequest({
- url: server.url,
- path: '/plugins/test-four/router/commander',
- fields: body,
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-}
-
-describe('Test plugin helpers', function () {
- let servers: PeerTubeServer[]
-
- before(async function () {
- this.timeout(60000)
-
- servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
-
- await doubleFollow(servers[0], servers[1])
-
- await servers[0].plugins.install({ path: PluginsCommand.getPluginTestPath('-four') })
- })
-
- describe('Logger', function () {
-
- it('Should have logged things', async function () {
- await servers[0].servers.waitUntilLog(servers[0].host + ' peertube-plugin-test-four', 1, false)
- await servers[0].servers.waitUntilLog('Hello world from plugin four', 1)
- })
- })
-
- describe('Database', function () {
-
- it('Should have made a query', async function () {
- await servers[0].servers.waitUntilLog(`root email is admin${servers[0].internalServerNumber}@example.com`)
- })
- })
-
- describe('Config', function () {
-
- it('Should have the correct webserver url', async function () {
- await servers[0].servers.waitUntilLog(`server url is ${servers[0].url}`)
- })
-
- it('Should have the correct listening config', async function () {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/server-listening-config',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.config).to.exist
- expect(res.body.config.hostname).to.equal('::')
- expect(res.body.config.port).to.equal(servers[0].port)
- })
-
- it('Should have the correct config', async function () {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/server-config',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.serverConfig).to.exist
- expect(res.body.serverConfig.instance.name).to.equal('PeerTube')
- })
- })
-
- describe('Server', function () {
-
- it('Should get the server actor', async function () {
- await servers[0].servers.waitUntilLog('server actor name is peertube')
- })
- })
-
- describe('Socket', function () {
-
- it('Should sendNotification without any exceptions', async () => {
- const user = await servers[0].users.create({ username: 'notis_redding', password: 'secret1234?' })
- await makePostBodyRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/send-notification',
- fields: {
- userId: user.id
- },
- expectedStatus: HttpStatusCode.CREATED_201
- })
- })
-
- it('Should sendVideoLiveNewState without any exceptions', async () => {
- const res = await servers[0].videos.quickUpload({ name: 'video server 1' })
-
- await makePostBodyRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/send-video-live-new-state/' + res.uuid,
- expectedStatus: HttpStatusCode.CREATED_201
- })
-
- await servers[0].videos.remove({ id: res.uuid })
- })
- })
-
- describe('Plugin', function () {
-
- it('Should get the base static route', async function () {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/static-route',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.staticRoute).to.equal('/plugins/test-four/0.0.1/static/')
- })
-
- it('Should get the base static route', async function () {
- const baseRouter = '/plugins/test-four/0.0.1/router/'
-
- const res = await makeGetRequest({
- url: servers[0].url,
- path: baseRouter + 'router-route',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.routerRoute).to.equal(baseRouter)
- })
- })
-
- describe('User', function () {
- let rootId: number
-
- it('Should not get a user if not authenticated', async function () {
- await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/user',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should get a user if authenticated', async function () {
- const res = await makeGetRequest({
- url: servers[0].url,
- token: servers[0].accessToken,
- path: '/plugins/test-four/router/user',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.username).to.equal('root')
- expect(res.body.displayName).to.equal('root')
- expect(res.body.isAdmin).to.be.true
- expect(res.body.isModerator).to.be.false
- expect(res.body.isUser).to.be.false
-
- rootId = res.body.id
- })
-
- it('Should load a user by id', async function () {
- {
- const res = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/user/' + rootId,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.username).to.equal('root')
- }
-
- {
- await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/user/42',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- }
- })
- })
-
- describe('Moderation', function () {
- let videoUUIDServer1: string
-
- before(async function () {
- this.timeout(60000)
-
- {
- const res = await servers[0].videos.quickUpload({ name: 'video server 1' })
- videoUUIDServer1 = res.uuid
- }
-
- {
- await servers[1].videos.quickUpload({ name: 'video server 2' })
- }
-
- await waitJobs(servers)
-
- const { data } = await servers[0].videos.list()
-
- expect(data).to.have.lengthOf(2)
- })
-
- it('Should mute server 2', async function () {
- await postCommand(servers[0], 'blockServer', { hostToBlock: servers[1].host })
-
- const { data } = await servers[0].videos.list()
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('video server 1')
- })
-
- it('Should unmute server 2', async function () {
- await postCommand(servers[0], 'unblockServer', { hostToUnblock: servers[1].host })
-
- const { data } = await servers[0].videos.list()
-
- expect(data).to.have.lengthOf(2)
- })
-
- it('Should mute account of server 2', async function () {
- await postCommand(servers[0], 'blockAccount', { handleToBlock: `root@${servers[1].host}` })
-
- const { data } = await servers[0].videos.list()
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('video server 1')
- })
-
- it('Should unmute account of server 2', async function () {
- await postCommand(servers[0], 'unblockAccount', { handleToUnblock: `root@${servers[1].host}` })
-
- const { data } = await servers[0].videos.list()
-
- expect(data).to.have.lengthOf(2)
- })
-
- it('Should blacklist video', async function () {
- await postCommand(servers[0], 'blacklist', { videoUUID: videoUUIDServer1, unfederate: true })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- expect(data).to.have.lengthOf(1)
- expect(data[0].name).to.equal('video server 2')
- }
- })
-
- it('Should unblacklist video', async function () {
- await postCommand(servers[0], 'unblacklist', { videoUUID: videoUUIDServer1 })
-
- await waitJobs(servers)
-
- for (const server of servers) {
- const { data } = await server.videos.list()
-
- expect(data).to.have.lengthOf(2)
- }
- })
- })
-
- describe('Videos', function () {
- let videoUUID: string
- let videoPath: string
-
- before(async function () {
- this.timeout(240000)
-
- await servers[0].config.enableTranscoding()
-
- const res = await servers[0].videos.quickUpload({ name: 'video1' })
- videoUUID = res.uuid
-
- await waitJobs(servers)
- })
-
- it('Should get video files', async function () {
- const { body } = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/video-files/' + videoUUID,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- // Video files check
- {
- expect(body.webVideo.videoFiles).to.be.an('array')
- expect(body.hls.videoFiles).to.be.an('array')
-
- for (const resolution of [ 144, 240, 360, 480, 720 ]) {
- for (const files of [ body.webVideo.videoFiles, body.hls.videoFiles ]) {
- const file = files.find(f => f.resolution === resolution)
- expect(file).to.exist
-
- expect(file.size).to.be.a('number')
- expect(file.fps).to.equal(25)
-
- expect(await pathExists(file.path)).to.be.true
- await makeRawRequest({ url: file.url, expectedStatus: HttpStatusCode.OK_200 })
- }
- }
-
- videoPath = body.webVideo.videoFiles[0].path
- }
-
- // Thumbnails check
- {
- expect(body.thumbnails).to.be.an('array')
-
- const miniature = body.thumbnails.find(t => t.type === ThumbnailType.MINIATURE)
- expect(miniature).to.exist
- expect(await pathExists(miniature.path)).to.be.true
- await makeRawRequest({ url: miniature.url, expectedStatus: HttpStatusCode.OK_200 })
-
- const preview = body.thumbnails.find(t => t.type === ThumbnailType.PREVIEW)
- expect(preview).to.exist
- expect(await pathExists(preview.path)).to.be.true
- await makeRawRequest({ url: preview.url, expectedStatus: HttpStatusCode.OK_200 })
- }
- })
-
- it('Should probe a file', async function () {
- const { body } = await makeGetRequest({
- url: servers[0].url,
- path: '/plugins/test-four/router/ffprobe',
- query: {
- path: videoPath
- },
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(body.streams).to.be.an('array')
- expect(body.streams).to.have.lengthOf(2)
- })
-
- it('Should remove a video after a view', async function () {
- this.timeout(40000)
-
- // Should not throw -> video exists
- const video = await servers[0].videos.get({ id: videoUUID })
- // Should delete the video
- await servers[0].views.simulateView({ id: videoUUID })
-
- await servers[0].servers.waitUntilLog('Video deleted by plugin four.')
-
- try {
- // Should throw because the video should have been deleted
- await servers[0].videos.get({ id: videoUUID })
- throw new Error('Video exists')
- } catch (err) {
- if (err.message.includes('exists')) throw err
- }
-
- await checkVideoFilesWereRemoved({ server: servers[0], video })
- })
-
- it('Should have fetched the video by URL', async function () {
- await servers[0].servers.waitUntilLog(`video from DB uuid is ${videoUUID}`)
- })
- })
-
- after(async function () {
- await cleanupTests(servers)
- })
-})
diff --git a/server/tests/plugins/plugin-router.ts b/server/tests/plugins/plugin-router.ts
deleted file mode 100644
index 40b15eb79..000000000
--- a/server/tests/plugins/plugin-router.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- makePostBodyRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Test plugin helpers', function () {
- let server: PeerTubeServer
- const basePaths = [
- '/plugins/test-five/router/',
- '/plugins/test-five/0.0.1/router/'
- ]
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-five') })
- })
-
- it('Should answer "pong"', async function () {
- for (const path of basePaths) {
- const res = await makeGetRequest({
- url: server.url,
- path: path + 'ping',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.message).to.equal('pong')
- }
- })
-
- it('Should check if authenticated', async function () {
- for (const path of basePaths) {
- const res = await makeGetRequest({
- url: server.url,
- path: path + 'is-authenticated',
- token: server.accessToken,
- expectedStatus: 200
- })
-
- expect(res.body.isAuthenticated).to.equal(true)
-
- const secRes = await makeGetRequest({
- url: server.url,
- path: path + 'is-authenticated',
- expectedStatus: 200
- })
-
- expect(secRes.body.isAuthenticated).to.equal(false)
- }
- })
-
- it('Should mirror post body', async function () {
- const body = {
- hello: 'world',
- riri: 'fifi',
- loulou: 'picsou'
- }
-
- for (const path of basePaths) {
- const res = await makePostBodyRequest({
- url: server.url,
- path: path + 'form/post/mirror',
- fields: body,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body).to.deep.equal(body)
- }
- })
-
- it('Should remove the plugin and remove the routes', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-five' })
-
- for (const path of basePaths) {
- await makeGetRequest({
- url: server.url,
- path: path + 'ping',
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
-
- await makePostBodyRequest({
- url: server.url,
- path: path + 'ping',
- fields: {},
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/plugin-storage.ts b/server/tests/plugins/plugin-storage.ts
deleted file mode 100644
index 112652a1f..000000000
--- a/server/tests/plugins/plugin-storage.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir, readFile } from 'fs-extra'
-import { join } from 'path'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Test plugin storage', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-six') })
- })
-
- describe('DB storage', function () {
- it('Should correctly store a subkey', async function () {
- await server.servers.waitUntilLog('superkey stored value is toto')
- })
-
- it('Should correctly retrieve an array as array from the storage.', async function () {
- await server.servers.waitUntilLog('storedArrayKey isArray is true')
- await server.servers.waitUntilLog('storedArrayKey stored value is toto, toto2')
- })
- })
-
- describe('Disk storage', function () {
- let dataPath: string
- let pluginDataPath: string
-
- async function getFileContent () {
- const files = await readdir(pluginDataPath)
- expect(files).to.have.lengthOf(1)
-
- return readFile(join(pluginDataPath, files[0]), 'utf8')
- }
-
- before(function () {
- dataPath = server.servers.buildDirectory('plugins/data')
- pluginDataPath = join(dataPath, 'peertube-plugin-test-six')
- })
-
- it('Should have created the directory on install', async function () {
- const dataPath = server.servers.buildDirectory('plugins/data')
- const pluginDataPath = join(dataPath, 'peertube-plugin-test-six')
-
- expect(await pathExists(dataPath)).to.be.true
- expect(await pathExists(pluginDataPath)).to.be.true
- expect(await readdir(pluginDataPath)).to.have.lengthOf(0)
- })
-
- it('Should have created a file', async function () {
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path: '/plugins/test-six/router/create-file',
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const content = await getFileContent()
- expect(content).to.equal('Prince Ali')
- })
-
- it('Should still have the file after an uninstallation', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-six' })
-
- const content = await getFileContent()
- expect(content).to.equal('Prince Ali')
- })
-
- it('Should still have the file after the reinstallation', async function () {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-six') })
-
- const content = await getFileContent()
- expect(content).to.equal('Prince Ali')
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/plugin-transcoding.ts b/server/tests/plugins/plugin-transcoding.ts
deleted file mode 100644
index 21f82fbac..000000000
--- a/server/tests/plugins/plugin-transcoding.ts
+++ /dev/null
@@ -1,279 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { getAudioStream, getVideoStream, getVideoStreamFPS } from '@shared/ffmpeg'
-import { VideoPrivacy } from '@shared/models'
-import {
- cleanupTests,
- createSingleServer,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- testFfmpegStreamError,
- waitJobs
-} from '@shared/server-commands'
-
-async function createLiveWrapper (server: PeerTubeServer) {
- const liveAttributes = {
- name: 'live video',
- channelId: server.store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
-
- const { uuid } = await server.live.create({ fields: liveAttributes })
-
- return uuid
-}
-
-function updateConf (server: PeerTubeServer, vodProfile: string, liveProfile: string) {
- return server.config.updateCustomSubConfig({
- newConfig: {
- transcoding: {
- enabled: true,
- profile: vodProfile,
- hls: {
- enabled: true
- },
- webVideos: {
- enabled: true
- },
- resolutions: {
- '240p': true,
- '360p': false,
- '480p': false,
- '720p': true
- }
- },
- live: {
- transcoding: {
- profile: liveProfile,
- enabled: true,
- resolutions: {
- '240p': true,
- '360p': false,
- '480p': false,
- '720p': true
- }
- }
- }
- }
- })
-}
-
-describe('Test transcoding plugins', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(60000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
- await setDefaultVideoChannel([ server ])
-
- await updateConf(server, 'default', 'default')
- })
-
- describe('When using a plugin adding profiles to existing encoders', function () {
-
- async function checkVideoFPS (uuid: string, type: 'above' | 'below', fps: number) {
- const video = await server.videos.get({ id: uuid })
- const files = video.files.concat(...video.streamingPlaylists.map(p => p.files))
-
- for (const file of files) {
- if (type === 'above') {
- expect(file.fps).to.be.above(fps)
- } else {
- expect(file.fps).to.be.below(fps)
- }
- }
- }
-
- async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) {
- const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8`
- const videoFPS = await getVideoStreamFPS(playlistUrl)
-
- if (type === 'above') {
- expect(videoFPS).to.be.above(fps)
- } else {
- expect(videoFPS).to.be.below(fps)
- }
- }
-
- before(async function () {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
- })
-
- it('Should have the appropriate available profiles', async function () {
- const config = await server.config.getConfig()
-
- expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ])
- expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'high-live', 'input-options-live', 'bad-scale-live' ])
- })
-
- describe('VOD', function () {
-
- it('Should not use the plugin profile if not chosen by the admin', async function () {
- this.timeout(240000)
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
- await waitJobs([ server ])
-
- await checkVideoFPS(videoUUID, 'above', 20)
- })
-
- it('Should use the vod profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'low-vod', 'default')
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
- await waitJobs([ server ])
-
- await checkVideoFPS(videoUUID, 'below', 12)
- })
-
- it('Should apply input options in vod profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'input-options-vod', 'default')
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
- await waitJobs([ server ])
-
- await checkVideoFPS(videoUUID, 'below', 6)
- })
-
- it('Should apply the scale filter in vod profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'bad-scale-vod', 'default')
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video' })).uuid
- await waitJobs([ server ])
-
- // Transcoding failed
- const video = await server.videos.get({ id: videoUUID })
- expect(video.files).to.have.lengthOf(1)
- expect(video.streamingPlaylists).to.have.lengthOf(0)
- })
- })
-
- describe('Live', function () {
-
- it('Should not use the plugin profile if not chosen by the admin', async function () {
- this.timeout(240000)
-
- const liveVideoId = await createLiveWrapper(server)
-
- await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
- await server.live.waitUntilPublished({ videoId: liveVideoId })
- await waitJobs([ server ])
-
- await checkLiveFPS(liveVideoId, 'above', 20)
- })
-
- it('Should use the live profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'low-vod', 'high-live')
-
- const liveVideoId = await createLiveWrapper(server)
-
- await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
- await server.live.waitUntilPublished({ videoId: liveVideoId })
- await waitJobs([ server ])
-
- await checkLiveFPS(liveVideoId, 'above', 45)
- })
-
- it('Should apply the input options on live profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'low-vod', 'input-options-live')
-
- const liveVideoId = await createLiveWrapper(server)
-
- await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
- await server.live.waitUntilPublished({ videoId: liveVideoId })
- await waitJobs([ server ])
-
- await checkLiveFPS(liveVideoId, 'above', 45)
- })
-
- it('Should apply the scale filter name on live profile', async function () {
- this.timeout(240000)
-
- await updateConf(server, 'low-vod', 'bad-scale-live')
-
- const liveVideoId = await createLiveWrapper(server)
-
- const command = await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
- await testFfmpegStreamError(command, true)
- })
-
- it('Should default to the default profile if the specified profile does not exist', async function () {
- this.timeout(240000)
-
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
-
- const config = await server.config.getConfig()
-
- expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
- expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
- await waitJobs([ server ])
-
- await checkVideoFPS(videoUUID, 'above', 20)
- })
- })
-
- })
-
- describe('When using a plugin adding new encoders', function () {
-
- before(async function () {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
-
- await updateConf(server, 'test-vod-profile', 'test-live-profile')
- })
-
- it('Should use the new vod encoders', async function () {
- this.timeout(240000)
-
- const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
- await waitJobs([ server ])
-
- const video = await server.videos.get({ id: videoUUID })
-
- const path = server.servers.buildWebVideoFilePath(video.files[0].fileUrl)
- const audioProbe = await getAudioStream(path)
- expect(audioProbe.audioStream.codec_name).to.equal('opus')
-
- const videoProbe = await getVideoStream(path)
- expect(videoProbe.codec_name).to.equal('vp9')
- })
-
- it('Should use the new live encoders', async function () {
- this.timeout(240000)
-
- const liveVideoId = await createLiveWrapper(server)
-
- await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
- await server.live.waitUntilPublished({ videoId: liveVideoId })
- await waitJobs([ server ])
-
- const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
- const audioProbe = await getAudioStream(playlistUrl)
- expect(audioProbe.audioStream.codec_name).to.equal('opus')
-
- const videoProbe = await getVideoStream(playlistUrl)
- expect(videoProbe.codec_name).to.equal('h264')
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/plugin-unloading.ts b/server/tests/plugins/plugin-unloading.ts
deleted file mode 100644
index 5aca1a0c0..000000000
--- a/server/tests/plugins/plugin-unloading.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { HttpStatusCode } from '@shared/models'
-
-describe('Test plugins module unloading', function () {
- let server: PeerTubeServer = null
- const requestPath = '/plugins/test-unloading/router/get'
- let value: string = null
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-unloading') })
- })
-
- it('Should return a numeric value', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: requestPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.message).to.match(/^\d+$/)
- value = res.body.message
- })
-
- it('Should return the same value the second time', async function () {
- const res = await makeGetRequest({
- url: server.url,
- path: requestPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.message).to.be.equal(value)
- })
-
- it('Should uninstall the plugin and free the route', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-unloading' })
-
- await makeGetRequest({
- url: server.url,
- path: requestPath,
- expectedStatus: HttpStatusCode.NOT_FOUND_404
- })
- })
-
- it('Should return a different numeric value', async function () {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-unloading') })
-
- const res = await makeGetRequest({
- url: server.url,
- path: requestPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- expect(res.body.message).to.match(/^\d+$/)
- expect(res.body.message).to.be.not.equal(value)
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/plugin-websocket.ts b/server/tests/plugins/plugin-websocket.ts
deleted file mode 100644
index adaa28b1d..000000000
--- a/server/tests/plugins/plugin-websocket.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import WebSocket from 'ws'
-import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers } from '@shared/server-commands'
-
-function buildWebSocket (server: PeerTubeServer, path: string) {
- return new WebSocket('ws://' + server.host + path)
-}
-
-function expectErrorOrTimeout (server: PeerTubeServer, path: string, expectedTimeout: number) {
- return new Promise((res, rej) => {
- const ws = buildWebSocket(server, path)
- ws.on('error', () => res())
-
- const timeout = setTimeout(() => res(), expectedTimeout)
-
- ws.on('open', () => {
- clearTimeout(timeout)
-
- return rej(new Error('Connect did not timeout'))
- })
- })
-}
-
-describe('Test plugin websocket', function () {
- let server: PeerTubeServer
- const basePaths = [
- '/plugins/test-websocket/ws/',
- '/plugins/test-websocket/0.0.1/ws/'
- ]
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-websocket') })
- })
-
- it('Should not connect to the websocket without the appropriate path', async function () {
- const paths = [
- '/plugins/unknown/ws/',
- '/plugins/unknown/0.0.1/ws/'
- ]
-
- for (const path of paths) {
- await expectErrorOrTimeout(server, path, 1000)
- }
- })
-
- it('Should not connect to the websocket without the appropriate sub path', async function () {
- for (const path of basePaths) {
- await expectErrorOrTimeout(server, path + '/unknown', 1000)
- }
- })
-
- it('Should connect to the websocket and receive pong', function (done) {
- const ws = buildWebSocket(server, basePaths[0])
-
- ws.on('open', () => ws.send('ping'))
- ws.on('message', data => {
- if (data.toString() === 'pong') return done()
- })
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/translations.ts b/server/tests/plugins/translations.ts
deleted file mode 100644
index 67e4683f8..000000000
--- a/server/tests/plugins/translations.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers } from '@shared/server-commands'
-
-describe('Test plugin translations', function () {
- let server: PeerTubeServer
- let command: PluginsCommand
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- command = server.plugins
-
- await command.install({ path: PluginsCommand.getPluginTestPath() })
- await command.install({ path: PluginsCommand.getPluginTestPath('-filter-translations') })
- })
-
- it('Should not have translations for locale pt', async function () {
- const body = await command.getTranslations({ locale: 'pt' })
-
- expect(body).to.deep.equal({})
- })
-
- it('Should have translations for locale fr', async function () {
- const body = await command.getTranslations({ locale: 'fr-FR' })
-
- expect(body).to.deep.equal({
- 'peertube-plugin-test': {
- Hi: 'Coucou'
- },
- 'peertube-plugin-test-filter-translations': {
- 'Hello world': 'Bonjour le monde'
- }
- })
- })
-
- it('Should have translations of locale it', async function () {
- const body = await command.getTranslations({ locale: 'it-IT' })
-
- expect(body).to.deep.equal({
- 'peertube-plugin-test-filter-translations': {
- 'Hello world': 'Ciao, mondo!'
- }
- })
- })
-
- it('Should remove the plugin and remove the locales', async function () {
- await command.uninstall({ npmName: 'peertube-plugin-test-filter-translations' })
-
- {
- const body = await command.getTranslations({ locale: 'fr-FR' })
-
- expect(body).to.deep.equal({
- 'peertube-plugin-test': {
- Hi: 'Coucou'
- }
- })
- }
-
- {
- const body = await command.getTranslations({ locale: 'it-IT' })
-
- expect(body).to.deep.equal({})
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/plugins/video-constants.ts b/server/tests/plugins/video-constants.ts
deleted file mode 100644
index c388f02d1..000000000
--- a/server/tests/plugins/video-constants.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import {
- cleanupTests,
- createSingleServer,
- makeGetRequest,
- PeerTubeServer,
- PluginsCommand,
- setAccessTokensToServers
-} from '@shared/server-commands'
-import { HttpStatusCode, VideoPlaylistPrivacy } from '@shared/models'
-
-describe('Test plugin altering video constants', function () {
- let server: PeerTubeServer
-
- before(async function () {
- this.timeout(30000)
-
- server = await createSingleServer(1)
- await setAccessTokensToServers([ server ])
-
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-video-constants') })
- })
-
- it('Should have updated languages', async function () {
- const languages = await server.videos.getLanguages()
-
- expect(languages['en']).to.not.exist
- expect(languages['fr']).to.not.exist
-
- expect(languages['al_bhed']).to.equal('Al Bhed')
- expect(languages['al_bhed2']).to.equal('Al Bhed 2')
- expect(languages['al_bhed3']).to.not.exist
- })
-
- it('Should have updated categories', async function () {
- const categories = await server.videos.getCategories()
-
- expect(categories[1]).to.not.exist
- expect(categories[2]).to.not.exist
-
- expect(categories[42]).to.equal('Best category')
- expect(categories[43]).to.equal('High best category')
- })
-
- it('Should have updated licences', async function () {
- const licences = await server.videos.getLicences()
-
- expect(licences[1]).to.not.exist
- expect(licences[7]).to.not.exist
-
- expect(licences[42]).to.equal('Best licence')
- expect(licences[43]).to.equal('High best licence')
- })
-
- it('Should have updated video privacies', async function () {
- const privacies = await server.videos.getPrivacies()
-
- expect(privacies[1]).to.exist
- expect(privacies[2]).to.not.exist
- expect(privacies[3]).to.exist
- expect(privacies[4]).to.exist
- })
-
- it('Should have updated playlist privacies', async function () {
- const playlistPrivacies = await server.playlists.getPrivacies()
-
- expect(playlistPrivacies[1]).to.exist
- expect(playlistPrivacies[2]).to.exist
- expect(playlistPrivacies[3]).to.not.exist
- })
-
- it('Should not be able to create a video with this privacy', async function () {
- const attributes = { name: 'video', privacy: 2 }
- await server.videos.upload({ attributes, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should not be able to create a video with this privacy', async function () {
- const attributes = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
- await server.playlists.create({ attributes, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
- })
-
- it('Should be able to upload a video with these values', async function () {
- const attributes = { name: 'video', category: 42, licence: 42, language: 'al_bhed2' }
- const { uuid } = await server.videos.upload({ attributes })
-
- const video = await server.videos.get({ id: uuid })
- expect(video.language.label).to.equal('Al Bhed 2')
- expect(video.licence.label).to.equal('Best licence')
- expect(video.category.label).to.equal('Best category')
- })
-
- it('Should uninstall the plugin and reset languages, categories, licences and privacies', async function () {
- await server.plugins.uninstall({ npmName: 'peertube-plugin-test-video-constants' })
-
- {
- const languages = await server.videos.getLanguages()
-
- expect(languages['en']).to.equal('English')
- expect(languages['fr']).to.equal('French')
-
- expect(languages['al_bhed']).to.not.exist
- expect(languages['al_bhed2']).to.not.exist
- expect(languages['al_bhed3']).to.not.exist
- }
-
- {
- const categories = await server.videos.getCategories()
-
- expect(categories[1]).to.equal('Music')
- expect(categories[2]).to.equal('Films')
-
- expect(categories[42]).to.not.exist
- expect(categories[43]).to.not.exist
- }
-
- {
- const licences = await server.videos.getLicences()
-
- expect(licences[1]).to.equal('Attribution')
- expect(licences[7]).to.equal('Public Domain Dedication')
-
- expect(licences[42]).to.not.exist
- expect(licences[43]).to.not.exist
- }
-
- {
- const privacies = await server.videos.getPrivacies()
-
- expect(privacies[1]).to.exist
- expect(privacies[2]).to.exist
- expect(privacies[3]).to.exist
- expect(privacies[4]).to.exist
- }
-
- {
- const playlistPrivacies = await server.playlists.getPrivacies()
-
- expect(playlistPrivacies[1]).to.exist
- expect(playlistPrivacies[2]).to.exist
- expect(playlistPrivacies[3]).to.exist
- }
- })
-
- it('Should be able to reset categories', async function () {
- await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-video-constants') })
-
- {
- const categories = await server.videos.getCategories()
-
- expect(categories[1]).to.not.exist
- expect(categories[2]).to.not.exist
-
- expect(categories[42]).to.exist
- expect(categories[43]).to.exist
- }
-
- await makeGetRequest({
- url: server.url,
- token: server.accessToken,
- path: '/plugins/test-video-constants/router/reset-categories',
- expectedStatus: HttpStatusCode.NO_CONTENT_204
- })
-
- {
- const categories = await server.videos.getCategories()
-
- expect(categories[1]).to.exist
- expect(categories[2]).to.exist
-
- expect(categories[42]).to.not.exist
- expect(categories[43]).to.not.exist
- }
- })
-
- after(async function () {
- await cleanupTests([ server ])
- })
-})
diff --git a/server/tests/shared/actors.ts b/server/tests/shared/actors.ts
deleted file mode 100644
index 41fd72e89..000000000
--- a/server/tests/shared/actors.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { Account, VideoChannel } from '@shared/models'
-import { PeerTubeServer } from '@shared/server-commands'
-
-async function expectChannelsFollows (options: {
- server: PeerTubeServer
- handle: string
- followers: number
- following: number
-}) {
- const { server } = options
- const { data } = await server.channels.list()
-
- return expectActorFollow({ ...options, data })
-}
-
-async function expectAccountFollows (options: {
- server: PeerTubeServer
- handle: string
- followers: number
- following: number
-}) {
- const { server } = options
- const { data } = await server.accounts.list()
-
- return expectActorFollow({ ...options, data })
-}
-
-async function checkActorFilesWereRemoved (filename: string, server: PeerTubeServer) {
- for (const directory of [ 'avatars' ]) {
- const directoryPath = server.getDirectoryPath(directory)
-
- const directoryExists = await pathExists(directoryPath)
- expect(directoryExists).to.be.true
-
- const files = await readdir(directoryPath)
- for (const file of files) {
- expect(file).to.not.contain(filename)
- }
- }
-}
-
-export {
- expectAccountFollows,
- expectChannelsFollows,
- checkActorFilesWereRemoved
-}
-
-// ---------------------------------------------------------------------------
-
-function expectActorFollow (options: {
- server: PeerTubeServer
- data: (Account | VideoChannel)[]
- handle: string
- followers: number
- following: number
-}) {
- const { server, data, handle, followers, following } = options
-
- const actor = data.find(a => a.name + '@' + a.host === handle)
- const message = `${handle} on ${server.url}`
-
- expect(actor, message).to.exist
- expect(actor.followersCount).to.equal(followers, message)
- expect(actor.followingCount).to.equal(following, message)
-}
diff --git a/server/tests/shared/captions.ts b/server/tests/shared/captions.ts
deleted file mode 100644
index 35e722408..000000000
--- a/server/tests/shared/captions.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { expect } from 'chai'
-import request from 'supertest'
-import { HttpStatusCode } from '@shared/models'
-
-async function testCaptionFile (url: string, captionPath: string, toTest: RegExp | string) {
- const res = await request(url)
- .get(captionPath)
- .expect(HttpStatusCode.OK_200)
-
- if (toTest instanceof RegExp) {
- expect(res.text).to.match(toTest)
- } else {
- expect(res.text).to.contain(toTest)
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- testCaptionFile
-}
diff --git a/server/tests/shared/checks.ts b/server/tests/shared/checks.ts
deleted file mode 100644
index 90179c6ac..000000000
--- a/server/tests/shared/checks.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
-
-import { expect } from 'chai'
-import { pathExists, readFile } from 'fs-extra'
-import JPEG from 'jpeg-js'
-import { join } from 'path'
-import pixelmatch from 'pixelmatch'
-import { PNG } from 'pngjs'
-import { root } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import { makeGetRequest, PeerTubeServer } from '@shared/server-commands'
-
-// Default interval -> 5 minutes
-function dateIsValid (dateString: string | Date, interval = 300000) {
- const dateToCheck = new Date(dateString)
- const now = new Date()
-
- return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
-}
-
-function expectStartWith (str: string, start: string) {
- expect(str.startsWith(start), `${str} does not start with ${start}`).to.be.true
-}
-
-function expectNotStartWith (str: string, start: string) {
- expect(str.startsWith(start), `${str} does not start with ${start}`).to.be.false
-}
-
-function expectEndWith (str: string, end: string) {
- expect(str.endsWith(end), `${str} does not end with ${end}`).to.be.true
-}
-
-// ---------------------------------------------------------------------------
-
-async function expectLogDoesNotContain (server: PeerTubeServer, str: string) {
- const content = await server.servers.getLogContent()
-
- expect(content.toString()).to.not.contain(str)
-}
-
-async function expectLogContain (server: PeerTubeServer, str: string) {
- const content = await server.servers.getLogContent()
-
- expect(content.toString()).to.contain(str)
-}
-
-async function testImageSize (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
- const res = await makeGetRequest({
- url,
- path: imageHTTPPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const body = res.body
-
- const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
- const minLength = data.length - ((40 * data.length) / 100)
- const maxLength = data.length + ((40 * data.length) / 100)
-
- expect(body.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
- expect(body.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
-}
-
-async function testImageGeneratedByFFmpeg (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
- if (process.env.ENABLE_FFMPEG_THUMBNAIL_PIXEL_COMPARISON_TESTS !== 'true') {
- console.log(
- 'Pixel comparison of image generated by ffmpeg is disabled. ' +
- 'You can enable it using `ENABLE_FFMPEG_THUMBNAIL_PIXEL_COMPARISON_TESTS=true env variable')
- }
-
- return testImage(url, imageName, imageHTTPPath, extension)
-}
-
-async function testImage (url: string, imageName: string, imageHTTPPath: string, extension = '.jpg') {
- const res = await makeGetRequest({
- url,
- path: imageHTTPPath,
- expectedStatus: HttpStatusCode.OK_200
- })
-
- const body = res.body
- const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
-
- const img1 = imageHTTPPath.endsWith('.png')
- ? PNG.sync.read(body)
- : JPEG.decode(body)
-
- const img2 = extension === '.png'
- ? PNG.sync.read(data)
- : JPEG.decode(data)
-
- const result = pixelmatch(img1.data, img2.data, null, img1.width, img1.height, { threshold: 0.1 })
-
- expect(result).to.equal(0, `${imageHTTPPath} image is not the same as ${imageName}${extension}`)
-}
-
-async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
- const base = server.servers.buildDirectory(directory)
-
- expect(await pathExists(join(base, filePath))).to.equal(exist)
-}
-
-// ---------------------------------------------------------------------------
-
-function checkBadStartPagination (url: string, path: string, token?: string, query = {}) {
- return makeGetRequest({
- url,
- path,
- token,
- query: { ...query, start: 'hello' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-}
-
-async function checkBadCountPagination (url: string, path: string, token?: string, query = {}) {
- await makeGetRequest({
- url,
- path,
- token,
- query: { ...query, count: 'hello' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-
- await makeGetRequest({
- url,
- path,
- token,
- query: { ...query, count: 2000 },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-}
-
-function checkBadSortPagination (url: string, path: string, token?: string, query = {}) {
- return makeGetRequest({
- url,
- path,
- token,
- query: { ...query, sort: 'hello' },
- expectedStatus: HttpStatusCode.BAD_REQUEST_400
- })
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkVideoDuration (server: PeerTubeServer, videoUUID: string, duration: number) {
- const video = await server.videos.get({ id: videoUUID })
-
- expect(video.duration).to.be.approximately(duration, 1)
-
- for (const file of video.files) {
- const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
-
- for (const stream of metadata.streams) {
- expect(Math.round(stream.duration)).to.be.approximately(duration, 1)
- }
- }
-}
-
-export {
- dateIsValid,
- testImageGeneratedByFFmpeg,
- testImageSize,
- testImage,
- expectLogDoesNotContain,
- testFileExistsOrNot,
- expectStartWith,
- expectNotStartWith,
- expectEndWith,
- checkBadStartPagination,
- checkBadCountPagination,
- checkBadSortPagination,
- checkVideoDuration,
- expectLogContain
-}
diff --git a/server/tests/shared/directories.ts b/server/tests/shared/directories.ts
deleted file mode 100644
index 5ad12d78a..000000000
--- a/server/tests/shared/directories.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { homedir } from 'os'
-import { join } from 'path'
-import { PeerTubeServer } from '@shared/server-commands'
-import { PeerTubeRunnerProcess } from './peertube-runner-process'
-
-export async function checkTmpIsEmpty (server: PeerTubeServer) {
- await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ])
-
- if (await pathExists(server.getDirectoryPath('tmp/hls'))) {
- await checkDirectoryIsEmpty(server, 'tmp/hls')
- }
-}
-
-export async function checkPersistentTmpIsEmpty (server: PeerTubeServer) {
- await checkDirectoryIsEmpty(server, 'tmp-persistent')
-}
-
-export async function checkDirectoryIsEmpty (server: PeerTubeServer, directory: string, exceptions: string[] = []) {
- const directoryPath = server.getDirectoryPath(directory)
-
- const directoryExists = await pathExists(directoryPath)
- expect(directoryExists).to.be.true
-
- const files = await readdir(directoryPath)
- const filtered = files.filter(f => exceptions.includes(f) === false)
-
- expect(filtered).to.have.lengthOf(0)
-}
-
-export async function checkPeerTubeRunnerCacheIsEmpty (runner: PeerTubeRunnerProcess) {
- const directoryPath = join(homedir(), '.cache', 'peertube-runner-nodejs', runner.getId(), 'transcoding')
-
- const directoryExists = await pathExists(directoryPath)
- expect(directoryExists).to.be.true
-
- const files = await readdir(directoryPath)
-
- expect(files, 'Directory content: ' + files.join(', ')).to.have.lengthOf(0)
-}
diff --git a/server/tests/shared/generate.ts b/server/tests/shared/generate.ts
deleted file mode 100644
index 3788b049f..000000000
--- a/server/tests/shared/generate.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { expect } from 'chai'
-import ffmpeg from 'fluent-ffmpeg'
-import { ensureDir, pathExists } from 'fs-extra'
-import { dirname } from 'path'
-import { buildAbsoluteFixturePath, getMaxTheoreticalBitrate } from '@shared/core-utils'
-import { getVideoStreamBitrate, getVideoStreamDimensionsInfo, getVideoStreamFPS } from '@shared/ffmpeg'
-
-async function ensureHasTooBigBitrate (fixturePath: string) {
- const bitrate = await getVideoStreamBitrate(fixturePath)
- const dataResolution = await getVideoStreamDimensionsInfo(fixturePath)
- const fps = await getVideoStreamFPS(fixturePath)
-
- const maxBitrate = getMaxTheoreticalBitrate({ ...dataResolution, fps })
- expect(bitrate).to.be.above(maxBitrate)
-}
-
-async function generateHighBitrateVideo () {
- const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
-
- await ensureDir(dirname(tempFixturePath))
-
- const exists = await pathExists(tempFixturePath)
- if (!exists) {
- console.log('Generating high bitrate video.')
-
- // Generate a random, high bitrate video on the fly, so we don't have to include
- // a large file in the repo. The video needs to have a certain minimum length so
- // that FFmpeg properly applies bitrate limits.
- // https://stackoverflow.com/a/15795112
- return new Promise((res, rej) => {
- ffmpeg()
- .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
- .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
- .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
- .output(tempFixturePath)
- .on('error', rej)
- .on('end', () => res(tempFixturePath))
- .run()
- })
- }
-
- await ensureHasTooBigBitrate(tempFixturePath)
-
- return tempFixturePath
-}
-
-async function generateVideoWithFramerate (fps = 60) {
- const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
-
- await ensureDir(dirname(tempFixturePath))
-
- const exists = await pathExists(tempFixturePath)
- if (!exists) {
- console.log('Generating video with framerate %d.', fps)
-
- return new Promise((res, rej) => {
- ffmpeg()
- .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
- .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
- .outputOptions([ `-r ${fps}` ])
- .output(tempFixturePath)
- .on('error', rej)
- .on('end', () => res(tempFixturePath))
- .run()
- })
- }
-
- return tempFixturePath
-}
-
-export {
- generateHighBitrateVideo,
- generateVideoWithFramerate
-}
diff --git a/server/tests/shared/index.ts b/server/tests/shared/index.ts
deleted file mode 100644
index eda24adb5..000000000
--- a/server/tests/shared/index.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export * from './mock-servers'
-export * from './actors'
-export * from './captions'
-export * from './checks'
-export * from './directories'
-export * from './generate'
-export * from './live'
-export * from './notifications'
-export * from './peertube-runner-process'
-export * from './video-playlists'
-export * from './plugins'
-export * from './requests'
-export * from './sql-command'
-export * from './streaming-playlists'
-export * from './tests'
-export * from './tracker'
-export * from './videos'
-export * from './views'
-export * from './webtorrent'
diff --git a/server/tests/shared/live.ts b/server/tests/shared/live.ts
deleted file mode 100644
index 9d8c1d941..000000000
--- a/server/tests/shared/live.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { join } from 'path'
-import { sha1 } from '@shared/extra-utils'
-import { LiveVideo, VideoStreamingPlaylistType } from '@shared/models'
-import { ObjectStorageCommand, PeerTubeServer } from '@shared/server-commands'
-import { SQLCommand } from './sql-command'
-import { checkLiveSegmentHash, checkResolutionsInMasterPlaylist } from './streaming-playlists'
-
-async function checkLiveCleanup (options: {
- server: PeerTubeServer
- videoUUID: string
- permanent: boolean
- savedResolutions?: number[]
-}) {
- const { server, videoUUID, permanent, savedResolutions = [] } = options
-
- const basePath = server.servers.buildDirectory('streaming-playlists')
- const hlsPath = join(basePath, 'hls', videoUUID)
-
- if (permanent) {
- if (!await pathExists(hlsPath)) return
-
- const files = await readdir(hlsPath)
- expect(files).to.have.lengthOf(0)
- return
- }
-
- if (savedResolutions.length === 0) {
- return checkUnsavedLiveCleanup(server, videoUUID, hlsPath)
- }
-
- return checkSavedLiveCleanup(hlsPath, savedResolutions)
-}
-
-// ---------------------------------------------------------------------------
-
-async function testLiveVideoResolutions (options: {
- sqlCommand: SQLCommand
- originServer: PeerTubeServer
-
- servers: PeerTubeServer[]
- liveVideoId: string
- resolutions: number[]
- transcoded: boolean
-
- objectStorage?: ObjectStorageCommand
- objectStorageBaseUrl?: string
-}) {
- const {
- originServer,
- sqlCommand,
- servers,
- liveVideoId,
- resolutions,
- transcoded,
- objectStorage,
- objectStorageBaseUrl = objectStorage?.getMockPlaylistBaseUrl()
- } = options
-
- for (const server of servers) {
- const { data } = await server.videos.list()
- expect(data.find(v => v.uuid === liveVideoId)).to.exist
-
- const video = await server.videos.get({ id: liveVideoId })
- expect(video.streamingPlaylists).to.have.lengthOf(1)
-
- const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
- expect(hlsPlaylist).to.exist
- expect(hlsPlaylist.files).to.have.lengthOf(0) // Only fragmented mp4 files are displayed
-
- await checkResolutionsInMasterPlaylist({
- server,
- playlistUrl: hlsPlaylist.playlistUrl,
- resolutions,
- transcoded,
- withRetry: !!objectStorage
- })
-
- if (objectStorage) {
- expect(hlsPlaylist.playlistUrl).to.contain(objectStorageBaseUrl)
- }
-
- for (let i = 0; i < resolutions.length; i++) {
- const segmentNum = 3
- const segmentName = `${i}-00000${segmentNum}.ts`
- await originServer.live.waitUntilSegmentGeneration({
- server: originServer,
- videoUUID: video.uuid,
- playlistNumber: i,
- segment: segmentNum,
- objectStorage,
- objectStorageBaseUrl
- })
-
- const baseUrl = objectStorage
- ? join(objectStorageBaseUrl, 'hls')
- : originServer.url + '/static/streaming-playlists/hls'
-
- if (objectStorage) {
- expect(hlsPlaylist.segmentsSha256Url).to.contain(objectStorageBaseUrl)
- }
-
- const subPlaylist = await originServer.streamingPlaylists.get({
- url: `${baseUrl}/${video.uuid}/${i}.m3u8`,
- withRetry: !!objectStorage // With object storage, the request may fail because of inconsistent data in S3
- })
-
- expect(subPlaylist).to.contain(segmentName)
-
- await checkLiveSegmentHash({
- server,
- baseUrlSegment: baseUrl,
- videoUUID: video.uuid,
- segmentName,
- hlsPlaylist,
- withRetry: !!objectStorage // With object storage, the request may fail because of inconsistent data in S3
- })
-
- if (originServer.internalServerNumber === server.internalServerNumber) {
- const infohash = sha1(`${2 + hlsPlaylist.playlistUrl}+V${i}`)
- const dbInfohashes = await sqlCommand.getPlaylistInfohash(hlsPlaylist.id)
-
- expect(dbInfohashes).to.include(infohash)
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- checkLiveCleanup,
- testLiveVideoResolutions
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkSavedLiveCleanup (hlsPath: string, savedResolutions: number[] = []) {
- const files = await readdir(hlsPath)
-
- // fragmented file and playlist per resolution + master playlist + segments sha256 json file
- expect(files, `Directory content: ${files.join(', ')}`).to.have.lengthOf(savedResolutions.length * 2 + 2)
-
- for (const resolution of savedResolutions) {
- const fragmentedFile = files.find(f => f.endsWith(`-${resolution}-fragmented.mp4`))
- expect(fragmentedFile).to.exist
-
- const playlistFile = files.find(f => f.endsWith(`${resolution}.m3u8`))
- expect(playlistFile).to.exist
- }
-
- const masterPlaylistFile = files.find(f => f.endsWith('-master.m3u8'))
- expect(masterPlaylistFile).to.exist
-
- const shaFile = files.find(f => f.endsWith('-segments-sha256.json'))
- expect(shaFile).to.exist
-}
-
-async function checkUnsavedLiveCleanup (server: PeerTubeServer, videoUUID: string, hlsPath: string) {
- let live: LiveVideo
-
- try {
- live = await server.live.get({ videoId: videoUUID })
- } catch {}
-
- if (live?.permanentLive) {
- expect(await pathExists(hlsPath)).to.be.true
-
- const hlsFiles = await readdir(hlsPath)
- expect(hlsFiles).to.have.lengthOf(1) // Only replays directory
-
- const replayDir = join(hlsPath, 'replay')
- expect(await pathExists(replayDir)).to.be.true
-
- const replayFiles = await readdir(join(hlsPath, 'replay'))
- expect(replayFiles).to.have.lengthOf(0)
-
- return
- }
-
- expect(await pathExists(hlsPath)).to.be.false
-}
diff --git a/server/tests/shared/mock-servers/index.ts b/server/tests/shared/mock-servers/index.ts
deleted file mode 100644
index 1fa983116..000000000
--- a/server/tests/shared/mock-servers/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export * from './mock-429'
-export * from './mock-email'
-export * from './mock-http'
-export * from './mock-instances-index'
-export * from './mock-joinpeertube-versions'
-export * from './mock-object-storage'
-export * from './mock-plugin-blocklist'
-export * from './mock-proxy'
diff --git a/server/tests/shared/mock-servers/mock-429.ts b/server/tests/shared/mock-servers/mock-429.ts
deleted file mode 100644
index 1fc20b079..000000000
--- a/server/tests/shared/mock-servers/mock-429.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './shared'
-
-export class Mock429 {
- private server: Server
- private responseSent = false
-
- async initialize () {
- const app = express()
-
- app.get('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
-
- if (!this.responseSent) {
- this.responseSent = true
-
- // Retry after 5 seconds
- res.header('retry-after', '2')
- return res.sendStatus(429)
- }
-
- return res.sendStatus(200)
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-email.ts b/server/tests/shared/mock-servers/mock-email.ts
deleted file mode 100644
index 6eda2dfda..000000000
--- a/server/tests/shared/mock-servers/mock-email.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import MailDev from '@peertube/maildev'
-import { parallelTests, randomInt } from '@shared/core-utils'
-
-class MockSmtpServer {
-
- private static instance: MockSmtpServer
- private started = false
- private maildev: any
- private emails: object[]
-
- private constructor () { }
-
- collectEmails (emailsCollection: object[]) {
- return new Promise((res, rej) => {
- const port = parallelTests() ? randomInt(1025, 2000) : 1025
- this.emails = emailsCollection
-
- if (this.started) {
- return res(undefined)
- }
-
- this.maildev = new MailDev({
- ip: '127.0.0.1',
- smtp: port,
- disableWeb: true,
- silent: true
- })
-
- this.maildev.on('new', email => {
- this.emails.push(email)
- })
-
- this.maildev.listen(err => {
- if (err) return rej(err)
-
- this.started = true
-
- return res(port)
- })
- })
- }
-
- kill () {
- if (!this.maildev) return
-
- this.maildev.close()
-
- this.maildev = null
- MockSmtpServer.instance = null
- }
-
- static get Instance () {
- return this.instance || (this.instance = new this())
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- MockSmtpServer
-}
diff --git a/server/tests/shared/mock-servers/mock-http.ts b/server/tests/shared/mock-servers/mock-http.ts
deleted file mode 100644
index b7a019e07..000000000
--- a/server/tests/shared/mock-servers/mock-http.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './shared'
-
-export class MockHTTP {
- private server: Server
-
- async initialize () {
- const app = express()
-
- app.get('/*', (req: express.Request, res: express.Response, next: express.NextFunction) => {
- return res.sendStatus(200)
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-instances-index.ts b/server/tests/shared/mock-servers/mock-instances-index.ts
deleted file mode 100644
index 598b007f1..000000000
--- a/server/tests/shared/mock-servers/mock-instances-index.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './shared'
-
-export class MockInstancesIndex {
- private server: Server
-
- private readonly indexInstances: { host: string, createdAt: string }[] = []
-
- async initialize () {
- const app = express()
-
- app.use('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (process.env.DEBUG) console.log('Receiving request on mocked server %s.', req.url)
-
- return next()
- })
-
- app.get('/api/v1/instances/hosts', (req: express.Request, res: express.Response) => {
- const since = req.query.since
-
- const filtered = this.indexInstances.filter(i => {
- if (!since) return true
-
- return i.createdAt > since
- })
-
- return res.json({
- total: filtered.length,
- data: filtered
- })
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- addInstance (host: string) {
- this.indexInstances.push({ host, createdAt: new Date().toISOString() })
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-joinpeertube-versions.ts b/server/tests/shared/mock-servers/mock-joinpeertube-versions.ts
deleted file mode 100644
index 502f4e2f5..000000000
--- a/server/tests/shared/mock-servers/mock-joinpeertube-versions.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen } from './shared'
-
-export class MockJoinPeerTubeVersions {
- private server: Server
- private latestVersion: string
-
- async initialize () {
- const app = express()
-
- app.use('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (process.env.DEBUG) console.log('Receiving request on mocked server %s.', req.url)
-
- return next()
- })
-
- app.get('/versions.json', (req: express.Request, res: express.Response) => {
- return res.json({
- peertube: {
- latestVersion: this.latestVersion
- }
- })
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- setLatestVersion (latestVersion: string) {
- this.latestVersion = latestVersion
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-object-storage.ts b/server/tests/shared/mock-servers/mock-object-storage.ts
deleted file mode 100644
index ae76c4f3f..000000000
--- a/server/tests/shared/mock-servers/mock-object-storage.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import express from 'express'
-import got, { RequestError } from 'got'
-import { Server } from 'http'
-import { pipeline } from 'stream'
-import { ObjectStorageCommand } from '@shared/server-commands'
-import { getPort, randomListen, terminateServer } from './shared'
-
-export class MockObjectStorageProxy {
- private server: Server
-
- async initialize () {
- const app = express()
-
- app.get('/:bucketName/:path(*)', (req: express.Request, res: express.Response, next: express.NextFunction) => {
- const url = `http://${req.params.bucketName}.${ObjectStorageCommand.getMockEndpointHost()}/${req.params.path}`
-
- if (process.env.DEBUG) {
- console.log('Receiving request on mocked server %s.', req.url)
- console.log('Proxifying request to %s', url)
- }
-
- return pipeline(
- got.stream(url, { throwHttpErrors: false }),
- res,
- (err: RequestError) => {
- if (!err) return
-
- console.error('Pipeline failed.', err)
- }
- )
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-plugin-blocklist.ts b/server/tests/shared/mock-servers/mock-plugin-blocklist.ts
deleted file mode 100644
index 5d6e01816..000000000
--- a/server/tests/shared/mock-servers/mock-plugin-blocklist.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import express, { Request, Response } from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './shared'
-
-type BlocklistResponse = {
- data: {
- value: string
- action?: 'add' | 'remove'
- updatedAt?: string
- }[]
-}
-
-export class MockBlocklist {
- private body: BlocklistResponse
- private server: Server
-
- async initialize () {
- const app = express()
-
- app.get('/blocklist', (req: Request, res: Response) => {
- return res.json(this.body)
- })
-
- this.server = await randomListen(app)
-
- return getPort(this.server)
- }
-
- replace (body: BlocklistResponse) {
- this.body = body
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
diff --git a/server/tests/shared/mock-servers/mock-proxy.ts b/server/tests/shared/mock-servers/mock-proxy.ts
deleted file mode 100644
index e741d6735..000000000
--- a/server/tests/shared/mock-servers/mock-proxy.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { createServer, Server } from 'http'
-import { createProxy } from 'proxy'
-import { getPort, terminateServer } from './shared'
-
-class MockProxy {
- private server: Server
-
- initialize () {
- return new Promise(res => {
- this.server = createProxy(createServer())
- this.server.listen(0, () => res(getPort(this.server)))
- })
- }
-
- terminate () {
- return terminateServer(this.server)
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- MockProxy
-}
diff --git a/server/tests/shared/mock-servers/shared.ts b/server/tests/shared/mock-servers/shared.ts
deleted file mode 100644
index 235642439..000000000
--- a/server/tests/shared/mock-servers/shared.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Express } from 'express'
-import { Server } from 'http'
-import { AddressInfo } from 'net'
-
-function randomListen (app: Express) {
- return new Promise(res => {
- const server = app.listen(0, () => res(server))
- })
-}
-
-function getPort (server: Server) {
- const address = server.address() as AddressInfo
-
- return address.port
-}
-
-function terminateServer (server: Server) {
- if (!server) return Promise.resolve()
-
- return new Promise((res, rej) => {
- server.close(err => {
- if (err) return rej(err)
-
- return res()
- })
- })
-}
-
-export {
- randomListen,
- getPort,
- terminateServer
-}
diff --git a/server/tests/shared/notifications.ts b/server/tests/shared/notifications.ts
deleted file mode 100644
index 6c0688d5a..000000000
--- a/server/tests/shared/notifications.ts
+++ /dev/null
@@ -1,889 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { inspect } from 'util'
-import {
- AbuseState,
- PluginType,
- UserNotification,
- UserNotificationSetting,
- UserNotificationSettingValue,
- UserNotificationType
-} from '@shared/models'
-import {
- ConfigCommand,
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultAccountAvatar,
- setDefaultChannelAvatar,
- setDefaultVideoChannel
-} from '@shared/server-commands'
-import { MockSmtpServer } from './mock-servers'
-
-type CheckerBaseParams = {
- server: PeerTubeServer
- emails: any[]
- socketNotifications: UserNotification[]
- token: string
- check?: { web: boolean, mail: boolean }
-}
-
-type CheckerType = 'presence' | 'absence'
-
-function getAllNotificationsSettings (): UserNotificationSetting {
- return {
- newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- myVideoStudioEditionFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
- newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
- }
-}
-
-async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
- const { videoName, shortUUID } = options
- const notificationType = UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkVideo(notification.video, videoName, shortUUID)
- checkActor(notification.video.channel)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.type !== UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION || n.video.name !== videoName
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- return text.indexOf(shortUUID) !== -1 && text.indexOf('Your subscription') !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkVideoIsPublished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
- const { videoName, shortUUID } = options
- const notificationType = UserNotificationType.MY_VIDEO_PUBLISHED
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkVideo(notification.video, videoName, shortUUID)
- checkActor(notification.video.channel)
- } else {
- expect(notification.video).to.satisfy(v => v === undefined || v.name !== videoName)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
- return text.includes(shortUUID) && text.includes('Your video')
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkVideoStudioEditionIsFinished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- checkType: CheckerType
-}) {
- const { videoName, shortUUID } = options
- const notificationType = UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkVideo(notification.video, videoName, shortUUID)
- checkActor(notification.video.channel)
- } else {
- expect(notification.video).to.satisfy(v => v === undefined || v.name !== videoName)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
- return text.includes(shortUUID) && text.includes('Edition of your video')
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
- videoName: string
- shortUUID: string
- url: string
- success: boolean
- checkType: CheckerType
-}) {
- const { videoName, shortUUID, url, success } = options
-
- const notificationType = success ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS : UserNotificationType.MY_VIDEO_IMPORT_ERROR
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.videoImport.targetUrl).to.equal(url)
-
- if (success) checkVideo(notification.videoImport.video, videoName, shortUUID)
- } else {
- expect(notification.videoImport).to.satisfy(i => i === undefined || i.targetUrl !== url)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
- const toFind = success ? ' finished' : ' error'
-
- return text.includes(url) && text.includes(toFind)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkUserRegistered (options: CheckerBaseParams & {
- username: string
- checkType: CheckerType
-}) {
- const { username } = options
- const notificationType = UserNotificationType.NEW_USER_REGISTRATION
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkActor(notification.account, { withAvatar: false })
- expect(notification.account.name).to.equal(username)
- } else {
- expect(notification).to.satisfy(n => n.type !== notificationType || n.account.name !== username)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes(' registered.') && text.includes(username)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkRegistrationRequest (options: CheckerBaseParams & {
- username: string
- registrationReason: string
- checkType: CheckerType
-}) {
- const { username, registrationReason } = options
- const notificationType = UserNotificationType.NEW_USER_REGISTRATION_REQUEST
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.registration.username).to.equal(username)
- } else {
- expect(notification).to.satisfy(n => n.type !== notificationType || n.registration.username !== username)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes(' wants to register ') && text.includes(username) && text.includes(registrationReason)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkNewActorFollow (options: CheckerBaseParams & {
- followType: 'channel' | 'account'
- followerName: string
- followerDisplayName: string
- followingDisplayName: string
- checkType: CheckerType
-}) {
- const { followType, followerName, followerDisplayName, followingDisplayName } = options
- const notificationType = UserNotificationType.NEW_FOLLOW
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkActor(notification.actorFollow.follower)
- expect(notification.actorFollow.follower.displayName).to.equal(followerDisplayName)
- expect(notification.actorFollow.follower.name).to.equal(followerName)
- expect(notification.actorFollow.follower.host).to.not.be.undefined
-
- const following = notification.actorFollow.following
- expect(following.displayName).to.equal(followingDisplayName)
- expect(following.type).to.equal(followType)
- } else {
- expect(notification).to.satisfy(n => {
- return n.type !== notificationType ||
- (n.actorFollow.follower.name !== followerName && n.actorFollow.following !== followingDisplayName)
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes(followType) && text.includes(followingDisplayName) && text.includes(followerDisplayName)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewInstanceFollower (options: CheckerBaseParams & {
- followerHost: string
- checkType: CheckerType
-}) {
- const { followerHost } = options
- const notificationType = UserNotificationType.NEW_INSTANCE_FOLLOWER
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkActor(notification.actorFollow.follower, { withAvatar: false })
- expect(notification.actorFollow.follower.name).to.equal('peertube')
- expect(notification.actorFollow.follower.host).to.equal(followerHost)
-
- expect(notification.actorFollow.following.name).to.equal('peertube')
- } else {
- expect(notification).to.satisfy(n => {
- return n.type !== notificationType || n.actorFollow.follower.host !== followerHost
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes('instance has a new follower') && text.includes(followerHost)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
- followerHost: string
- followingHost: string
- checkType: CheckerType
-}) {
- const { followerHost, followingHost } = options
- const notificationType = UserNotificationType.AUTO_INSTANCE_FOLLOWING
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- const following = notification.actorFollow.following
-
- checkActor(following, { withAvatar: false })
- expect(following.name).to.equal('peertube')
- expect(following.host).to.equal(followingHost)
-
- expect(notification.actorFollow.follower.name).to.equal('peertube')
- expect(notification.actorFollow.follower.host).to.equal(followerHost)
- } else {
- expect(notification).to.satisfy(n => {
- return n.type !== notificationType || n.actorFollow.following.host !== followingHost
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes(' automatically followed a new instance') && text.includes(followingHost)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkCommentMention (options: CheckerBaseParams & {
- shortUUID: string
- commentId: number
- threadId: number
- byAccountDisplayName: string
- checkType: CheckerType
-}) {
- const { shortUUID, commentId, threadId, byAccountDisplayName } = options
- const notificationType = UserNotificationType.COMMENT_MENTION
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkComment(notification.comment, commentId, threadId)
- checkActor(notification.comment.account)
- expect(notification.comment.account.displayName).to.equal(byAccountDisplayName)
-
- checkVideo(notification.comment.video, undefined, shortUUID)
- } else {
- expect(notification).to.satisfy(n => n.type !== notificationType || n.comment.id !== commentId)
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text: string = email['text']
-
- return text.includes(' mentioned ') && text.includes(shortUUID) && text.includes(byAccountDisplayName)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-let lastEmailCount = 0
-
-async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
- shortUUID: string
- commentId: number
- threadId: number
- checkType: CheckerType
-}) {
- const { server, shortUUID, commentId, threadId, checkType, emails } = options
- const notificationType = UserNotificationType.NEW_COMMENT_ON_MY_VIDEO
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- checkComment(notification.comment, commentId, threadId)
- checkActor(notification.comment.account)
- checkVideo(notification.comment.video, undefined, shortUUID)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.comment === undefined || n.comment.id !== commentId
- })
- }
- }
-
- const commentUrl = `${server.url}/w/${shortUUID};threadId=${threadId}`
-
- function emailNotificationFinder (email: object) {
- return email['text'].indexOf(commentUrl) !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-
- if (checkType === 'presence') {
- // We cannot detect email duplicates, so check we received another email
- expect(emails).to.have.length.above(lastEmailCount)
- lastEmailCount = emails.length
- }
-}
-
-async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
- const { shortUUID, videoName } = options
- const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.abuse.id).to.be.a('number')
- checkVideo(notification.abuse.video, videoName, shortUUID)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.video.shortUUID !== shortUUID
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewAbuseMessage (options: CheckerBaseParams & {
- abuseId: number
- message: string
- toEmail: string
- checkType: CheckerType
-}) {
- const { abuseId, message, toEmail } = options
- const notificationType = UserNotificationType.ABUSE_NEW_MESSAGE
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.abuse.id).to.equal(abuseId)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.type !== notificationType || n.abuse === undefined || n.abuse.id !== abuseId
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- const to = email['to'].filter(t => t.address === toEmail)
-
- return text.indexOf(message) !== -1 && to.length !== 0
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkAbuseStateChange (options: CheckerBaseParams & {
- abuseId: number
- state: AbuseState
- checkType: CheckerType
-}) {
- const { abuseId, state } = options
- const notificationType = UserNotificationType.ABUSE_STATE_CHANGE
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.abuse.id).to.equal(abuseId)
- expect(notification.abuse.state).to.equal(state)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.id !== abuseId
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
-
- const contains = state === AbuseState.ACCEPTED
- ? ' accepted'
- : ' rejected'
-
- return text.indexOf(contains) !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
- const { shortUUID, videoName } = options
- const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.abuse.id).to.be.a('number')
- checkVideo(notification.abuse.comment.video, videoName, shortUUID)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.comment.video.shortUUID !== shortUUID
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
- displayName: string
- checkType: CheckerType
-}) {
- const { displayName } = options
- const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.abuse.id).to.be.a('number')
- expect(notification.abuse.account.displayName).to.equal(displayName)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.abuse === undefined || n.abuse.account.displayName !== displayName
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- return text.indexOf(displayName) !== -1 && text.indexOf('abuse') !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- checkType: CheckerType
-}) {
- const { shortUUID, videoName } = options
- const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.videoBlacklist.video.id).to.be.a('number')
- checkVideo(notification.videoBlacklist.video, videoName, shortUUID)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.video === undefined || n.video.shortUUID !== shortUUID
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- return text.indexOf(shortUUID) !== -1 && email['text'].indexOf('video-auto-blacklist/list') !== -1
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
- shortUUID: string
- videoName: string
- blacklistType: 'blacklist' | 'unblacklist'
-}) {
- const { videoName, shortUUID, blacklistType } = options
- const notificationType = blacklistType === 'blacklist'
- ? UserNotificationType.BLACKLIST_ON_MY_VIDEO
- : UserNotificationType.UNBLACKLIST_ON_MY_VIDEO
-
- function notificationChecker (notification: UserNotification) {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- const video = blacklistType === 'blacklist' ? notification.videoBlacklist.video : notification.video
-
- checkVideo(video, videoName, shortUUID)
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
- const blacklistText = blacklistType === 'blacklist'
- ? 'blacklisted'
- : 'unblacklisted'
-
- return text.includes(shortUUID) && text.includes(blacklistText)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder, checkType: 'presence' })
-}
-
-async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
- latestVersion: string
- checkType: CheckerType
-}) {
- const { latestVersion } = options
- const notificationType = UserNotificationType.NEW_PEERTUBE_VERSION
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.peertube).to.exist
- expect(notification.peertube.latestVersion).to.equal(latestVersion)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.peertube === undefined || n.peertube.latestVersion !== latestVersion
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
-
- return text.includes(latestVersion)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewPluginVersion (options: CheckerBaseParams & {
- pluginType: PluginType
- pluginName: string
- checkType: CheckerType
-}) {
- const { pluginName, pluginType } = options
- const notificationType = UserNotificationType.NEW_PLUGIN_VERSION
-
- function notificationChecker (notification: UserNotification, checkType: CheckerType) {
- if (checkType === 'presence') {
- expect(notification).to.not.be.undefined
- expect(notification.type).to.equal(notificationType)
-
- expect(notification.plugin.name).to.equal(pluginName)
- expect(notification.plugin.type).to.equal(pluginType)
- } else {
- expect(notification).to.satisfy((n: UserNotification) => {
- return n === undefined || n.plugin === undefined || n.plugin.name !== pluginName
- })
- }
- }
-
- function emailNotificationFinder (email: object) {
- const text = email['text']
-
- return text.includes(pluginName)
- }
-
- await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) {
- const userNotifications: UserNotification[] = []
- const adminNotifications: UserNotification[] = []
- const adminNotificationsServer2: UserNotification[] = []
- const emails: object[] = []
-
- const port = await MockSmtpServer.Instance.collectEmails(emails)
-
- const overrideConfig = {
- ...ConfigCommand.getEmailOverrideConfig(port),
-
- signup: {
- limit: 20
- }
- }
- const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
-
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
- await setDefaultChannelAvatar(servers)
- await setDefaultAccountAvatar(servers)
-
- if (servers[1]) {
- await servers[1].config.enableStudio()
- await servers[1].config.enableLive({ allowReplay: true, transcoding: false })
- }
-
- if (serversCount > 1) {
- await doubleFollow(servers[0], servers[1])
- }
-
- const user = { username: 'user_1', password: 'super password' }
- await servers[0].users.create({ ...user, videoQuota: 10 * 1000 * 1000 })
- const userAccessToken = await servers[0].login.getAccessToken(user)
-
- await servers[0].notifications.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
- await servers[0].users.updateMyAvatar({ token: userAccessToken, fixture: 'avatar.png' })
- await servers[0].channels.updateImage({ channelName: 'user_1_channel', token: userAccessToken, fixture: 'avatar.png', type: 'avatar' })
-
- await servers[0].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
-
- if (serversCount > 1) {
- await servers[1].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
- }
-
- {
- const socket = servers[0].socketIO.getUserNotificationSocket({ token: userAccessToken })
- socket.on('new-notification', n => userNotifications.push(n))
- }
- {
- const socket = servers[0].socketIO.getUserNotificationSocket()
- socket.on('new-notification', n => adminNotifications.push(n))
- }
-
- if (serversCount > 1) {
- const socket = servers[1].socketIO.getUserNotificationSocket()
- socket.on('new-notification', n => adminNotificationsServer2.push(n))
- }
-
- const { videoChannels } = await servers[0].users.getMyInfo()
- const channelId = videoChannels[0].id
-
- return {
- userNotifications,
- adminNotifications,
- adminNotificationsServer2,
- userAccessToken,
- emails,
- servers,
- channelId,
- baseOverrideConfig: overrideConfig
- }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- getAllNotificationsSettings,
-
- CheckerBaseParams,
- CheckerType,
- checkMyVideoImportIsFinished,
- checkUserRegistered,
- checkAutoInstanceFollowing,
- checkVideoIsPublished,
- checkNewVideoFromSubscription,
- checkNewActorFollow,
- checkNewCommentOnMyVideo,
- checkNewBlacklistOnMyVideo,
- checkCommentMention,
- checkNewVideoAbuseForModerators,
- checkVideoAutoBlacklistForModerators,
- checkNewAbuseMessage,
- checkAbuseStateChange,
- checkNewInstanceFollower,
- prepareNotificationsTest,
- checkNewCommentAbuseForModerators,
- checkNewAccountAbuseForModerators,
- checkNewPeerTubeVersion,
- checkNewPluginVersion,
- checkVideoStudioEditionIsFinished,
- checkRegistrationRequest
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkNotification (options: CheckerBaseParams & {
- notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
- emailNotificationFinder: (email: object) => boolean
- checkType: CheckerType
-}) {
- const { server, token, checkType, notificationChecker, emailNotificationFinder, socketNotifications, emails } = options
-
- const check = options.check || { web: true, mail: true }
-
- if (check.web) {
- const notification = await server.notifications.getLatest({ token })
-
- if (notification || checkType !== 'absence') {
- notificationChecker(notification, checkType)
- }
-
- const socketNotification = socketNotifications.find(n => {
- try {
- notificationChecker(n, 'presence')
- return true
- } catch {
- return false
- }
- })
-
- if (checkType === 'presence') {
- const obj = inspect(socketNotifications, { depth: 5 })
- expect(socketNotification, 'The socket notification is absent when it should be present. ' + obj).to.not.be.undefined
- } else {
- const obj = inspect(socketNotification, { depth: 5 })
- expect(socketNotification, 'The socket notification is present when it should not be present. ' + obj).to.be.undefined
- }
- }
-
- if (check.mail) {
- // Last email
- const email = emails
- .slice()
- .reverse()
- .find(e => emailNotificationFinder(e))
-
- if (checkType === 'presence') {
- const texts = emails.map(e => e.text)
- expect(email, 'The email is absent when is should be present. ' + inspect(texts)).to.not.be.undefined
- } else {
- expect(email, 'The email is present when is should not be present. ' + inspect(email)).to.be.undefined
- }
- }
-}
-
-function checkVideo (video: any, videoName?: string, shortUUID?: string) {
- if (videoName) {
- expect(video.name).to.be.a('string')
- expect(video.name).to.not.be.empty
- expect(video.name).to.equal(videoName)
- }
-
- if (shortUUID) {
- expect(video.shortUUID).to.be.a('string')
- expect(video.shortUUID).to.not.be.empty
- expect(video.shortUUID).to.equal(shortUUID)
- }
-
- expect(video.id).to.be.a('number')
-}
-
-function checkActor (actor: any, options: { withAvatar?: boolean } = {}) {
- const { withAvatar = true } = options
-
- expect(actor.displayName).to.be.a('string')
- expect(actor.displayName).to.not.be.empty
- expect(actor.host).to.not.be.undefined
-
- if (withAvatar) {
- expect(actor.avatars).to.be.an('array')
- expect(actor.avatars).to.have.lengthOf(2)
- expect(actor.avatars[0].path).to.exist.and.not.empty
- }
-}
-
-function checkComment (comment: any, commentId: number, threadId: number) {
- expect(comment.id).to.equal(commentId)
- expect(comment.threadId).to.equal(threadId)
-}
diff --git a/server/tests/shared/peertube-runner-process.ts b/server/tests/shared/peertube-runner-process.ts
deleted file mode 100644
index 9304ebcc8..000000000
--- a/server/tests/shared/peertube-runner-process.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import { ChildProcess, fork } from 'child_process'
-import execa from 'execa'
-import { join } from 'path'
-import { root } from '@shared/core-utils'
-import { PeerTubeServer } from '@shared/server-commands'
-
-export class PeerTubeRunnerProcess {
- private app?: ChildProcess
-
- constructor (private readonly server: PeerTubeServer) {
-
- }
-
- runServer (options: {
- hideLogs?: boolean // default true
- } = {}) {
- const { hideLogs = true } = options
-
- return new Promise((res, rej) => {
- const args = [ 'server', '--verbose', ...this.buildIdArg() ]
-
- const forkOptions = {
- detached: false,
- silent: true
- }
- this.app = fork(this.getRunnerPath(), args, forkOptions)
-
- this.app.stdout.on('data', data => {
- const str = data.toString() as string
-
- if (!hideLogs) {
- console.log(str)
- }
- })
-
- res()
- })
- }
-
- registerPeerTubeInstance (options: {
- registrationToken: string
- runnerName: string
- runnerDescription?: string
- }) {
- const { registrationToken, runnerName, runnerDescription } = options
-
- const args = [
- 'register',
- '--url', this.server.url,
- '--registration-token', registrationToken,
- '--runner-name', runnerName,
- ...this.buildIdArg()
- ]
-
- if (runnerDescription) {
- args.push('--runner-description')
- args.push(runnerDescription)
- }
-
- return execa.node(this.getRunnerPath(), args)
- }
-
- unregisterPeerTubeInstance (options: {
- runnerName: string
- }) {
- const { runnerName } = options
-
- const args = [ 'unregister', '--url', this.server.url, '--runner-name', runnerName, ...this.buildIdArg() ]
- return execa.node(this.getRunnerPath(), args)
- }
-
- async listRegisteredPeerTubeInstances () {
- const args = [ 'list-registered', ...this.buildIdArg() ]
- const { stdout } = await execa.node(this.getRunnerPath(), args)
-
- return stdout
- }
-
- kill () {
- if (!this.app) return
-
- process.kill(this.app.pid)
-
- this.app = null
- }
-
- getId () {
- return 'test-' + this.server.internalServerNumber
- }
-
- private getRunnerPath () {
- return join(root(), 'packages', 'peertube-runner', 'dist', 'peertube-runner.js')
- }
-
- private buildIdArg () {
- return [ '--id', this.getId() ]
- }
-}
diff --git a/server/tests/shared/plugins.ts b/server/tests/shared/plugins.ts
deleted file mode 100644
index 036fce2ff..000000000
--- a/server/tests/shared/plugins.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { PeerTubeServer } from '@shared/server-commands'
-
-async function testHelloWorldRegisteredSettings (server: PeerTubeServer) {
- const body = await server.plugins.getRegisteredSettings({ npmName: 'peertube-plugin-hello-world' })
-
- const registeredSettings = body.registeredSettings
- expect(registeredSettings).to.have.length.at.least(1)
-
- const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name')
- expect(adminNameSettings).to.not.be.undefined
-}
-
-export {
- testHelloWorldRegisteredSettings
-}
diff --git a/server/tests/shared/requests.ts b/server/tests/shared/requests.ts
deleted file mode 100644
index 0cfeab7b2..000000000
--- a/server/tests/shared/requests.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { doRequest } from '@server/helpers/requests'
-
-export function makePOSTAPRequest (url: string, body: any, httpSignature: any, headers: any) {
- const options = {
- method: 'POST' as 'POST',
- json: body,
- httpSignature,
- headers
- }
-
- return doRequest(url, options)
-}
diff --git a/server/tests/shared/sql-command.ts b/server/tests/shared/sql-command.ts
deleted file mode 100644
index 5c53a8ac6..000000000
--- a/server/tests/shared/sql-command.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-import { QueryTypes, Sequelize } from 'sequelize'
-import { forceNumber } from '@shared/core-utils'
-import { PeerTubeServer } from '@shared/server-commands'
-
-export class SQLCommand {
- private sequelize: Sequelize
-
- constructor (private readonly server: PeerTubeServer) {
-
- }
-
- deleteAll (table: string) {
- const seq = this.getSequelize()
-
- const options = { type: QueryTypes.DELETE }
-
- return seq.query(`DELETE FROM "${table}"`, options)
- }
-
- async getVideoShareCount () {
- const [ { total } ] = await this.selectQuery<{ total: string }>(`SELECT COUNT(*) as total FROM "videoShare"`)
- if (total === null) return 0
-
- return parseInt(total, 10)
- }
-
- async getInternalFileUrl (fileId: number) {
- return this.selectQuery<{ fileUrl: string }>(`SELECT "fileUrl" FROM "videoFile" WHERE id = :fileId`, { fileId })
- .then(rows => rows[0].fileUrl)
- }
-
- setActorField (to: string, field: string, value: string) {
- return this.updateQuery(`UPDATE actor SET ${this.escapeColumnName(field)} = :value WHERE url = :to`, { value, to })
- }
-
- setVideoField (uuid: string, field: string, value: string) {
- return this.updateQuery(`UPDATE video SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid })
- }
-
- setPlaylistField (uuid: string, field: string, value: string) {
- return this.updateQuery(`UPDATE "videoPlaylist" SET ${this.escapeColumnName(field)} = :value WHERE uuid = :uuid`, { value, uuid })
- }
-
- async countVideoViewsOf (uuid: string) {
- const query = 'SELECT SUM("videoView"."views") AS "total" FROM "videoView" ' +
- `INNER JOIN "video" ON "video"."id" = "videoView"."videoId" WHERE "video"."uuid" = :uuid`
-
- const [ { total } ] = await this.selectQuery<{ total: number }>(query, { uuid })
- if (!total) return 0
-
- return forceNumber(total)
- }
-
- getActorImage (filename: string) {
- return this.selectQuery<{ width: number, height: number }>(`SELECT * FROM "actorImage" WHERE filename = :filename`, { filename })
- .then(rows => rows[0])
- }
-
- // ---------------------------------------------------------------------------
-
- setPluginVersion (pluginName: string, newVersion: string) {
- return this.setPluginField(pluginName, 'version', newVersion)
- }
-
- setPluginLatestVersion (pluginName: string, newVersion: string) {
- return this.setPluginField(pluginName, 'latestVersion', newVersion)
- }
-
- setPluginField (pluginName: string, field: string, value: string) {
- return this.updateQuery(
- `UPDATE "plugin" SET ${this.escapeColumnName(field)} = :value WHERE "name" = :pluginName`,
- { pluginName, value }
- )
- }
-
- // ---------------------------------------------------------------------------
-
- selectQuery (query: string, replacements: { [id: string]: string | number } = {}) {
- const seq = this.getSequelize()
- const options = {
- type: QueryTypes.SELECT as QueryTypes.SELECT,
- replacements
- }
-
- return seq.query(query, options)
- }
-
- updateQuery (query: string, replacements: { [id: string]: string | number } = {}) {
- const seq = this.getSequelize()
- const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, replacements }
-
- return seq.query(query, options)
- }
-
- // ---------------------------------------------------------------------------
-
- async getPlaylistInfohash (playlistId: number) {
- const query = 'SELECT "p2pMediaLoaderInfohashes" FROM "videoStreamingPlaylist" WHERE id = :playlistId'
-
- const result = await this.selectQuery<{ p2pMediaLoaderInfohashes: string }>(query, { playlistId })
- if (!result || result.length === 0) return []
-
- return result[0].p2pMediaLoaderInfohashes
- }
-
- // ---------------------------------------------------------------------------
-
- setActorFollowScores (newScore: number) {
- return this.updateQuery(`UPDATE "actorFollow" SET "score" = :newScore`, { newScore })
- }
-
- setTokenField (accessToken: string, field: string, value: string) {
- return this.updateQuery(
- `UPDATE "oAuthToken" SET ${this.escapeColumnName(field)} = :value WHERE "accessToken" = :accessToken`,
- { value, accessToken }
- )
- }
-
- async cleanup () {
- if (!this.sequelize) return
-
- await this.sequelize.close()
- this.sequelize = undefined
- }
-
- private getSequelize () {
- if (this.sequelize) return this.sequelize
-
- const dbname = 'peertube_test' + this.server.internalServerNumber
- const username = 'peertube'
- const password = 'peertube'
- const host = '127.0.0.1'
- const port = 5432
-
- this.sequelize = new Sequelize(dbname, username, password, {
- dialect: 'postgres',
- host,
- port,
- logging: false
- })
-
- return this.sequelize
- }
-
- private escapeColumnName (columnName: string) {
- return this.getSequelize().escape(columnName)
- .replace(/^'/, '"')
- .replace(/'$/, '"')
- }
-}
diff --git a/server/tests/shared/streaming-playlists.ts b/server/tests/shared/streaming-playlists.ts
deleted file mode 100644
index e4f88bc25..000000000
--- a/server/tests/shared/streaming-playlists.ts
+++ /dev/null
@@ -1,296 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { basename, dirname, join } from 'path'
-import { removeFragmentedMP4Ext, uuidRegex } from '@shared/core-utils'
-import { sha256 } from '@shared/extra-utils'
-import { HttpStatusCode, VideoPrivacy, VideoResolution, VideoStreamingPlaylist, VideoStreamingPlaylistType } from '@shared/models'
-import { makeRawRequest, PeerTubeServer } from '@shared/server-commands'
-import { expectStartWith } from './checks'
-import { hlsInfohashExist } from './tracker'
-import { checkWebTorrentWorks } from './webtorrent'
-
-async function checkSegmentHash (options: {
- server: PeerTubeServer
- baseUrlPlaylist: string
- baseUrlSegment: string
- resolution: number
- hlsPlaylist: VideoStreamingPlaylist
- token?: string
-}) {
- const { server, baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist, token } = options
- const command = server.streamingPlaylists
-
- const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
- const videoName = basename(file.fileUrl)
-
- const playlist = await command.get({ url: `${baseUrlPlaylist}/${removeFragmentedMP4Ext(videoName)}.m3u8`, token })
-
- const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
-
- const length = parseInt(matches[1], 10)
- const offset = parseInt(matches[2], 10)
- const range = `${offset}-${offset + length - 1}`
-
- const segmentBody = await command.getFragmentedSegment({
- url: `${baseUrlSegment}/${videoName}`,
- expectedStatus: HttpStatusCode.PARTIAL_CONTENT_206,
- range: `bytes=${range}`,
- token
- })
-
- const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url, token })
- expect(sha256(segmentBody)).to.equal(shaBody[videoName][range], `Invalid sha256 result for ${videoName} range ${range}`)
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkLiveSegmentHash (options: {
- server: PeerTubeServer
- baseUrlSegment: string
- videoUUID: string
- segmentName: string
- hlsPlaylist: VideoStreamingPlaylist
- withRetry?: boolean
-}) {
- const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist, withRetry = false } = options
- const command = server.streamingPlaylists
-
- const segmentBody = await command.getFragmentedSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}`, withRetry })
- const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url, withRetry })
-
- expect(sha256(segmentBody)).to.equal(shaBody[segmentName])
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkResolutionsInMasterPlaylist (options: {
- server: PeerTubeServer
- playlistUrl: string
- resolutions: number[]
- token?: string
- transcoded?: boolean // default true
- withRetry?: boolean // default false
-}) {
- const { server, playlistUrl, resolutions, token, withRetry = false, transcoded = true } = options
-
- const masterPlaylist = await server.streamingPlaylists.get({ url: playlistUrl, token, withRetry })
-
- for (const resolution of resolutions) {
- const base = '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution
-
- if (resolution === VideoResolution.H_NOVIDEO) {
- expect(masterPlaylist).to.match(new RegExp(`${base},CODECS="mp4a.40.2"`))
- } else if (transcoded) {
- expect(masterPlaylist).to.match(new RegExp(`${base},(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"`))
- } else {
- expect(masterPlaylist).to.match(new RegExp(`${base}`))
- }
- }
-
- const playlistsLength = masterPlaylist.split('\n').filter(line => line.startsWith('#EXT-X-STREAM-INF:BANDWIDTH='))
- expect(playlistsLength).to.have.lengthOf(resolutions.length)
-}
-
-async function completeCheckHlsPlaylist (options: {
- servers: PeerTubeServer[]
- videoUUID: string
- hlsOnly: boolean
-
- resolutions?: number[]
- objectStorageBaseUrl?: string
-}) {
- const { videoUUID, hlsOnly, objectStorageBaseUrl } = options
-
- const resolutions = options.resolutions ?? [ 240, 360, 480, 720 ]
-
- for (const server of options.servers) {
- const videoDetails = await server.videos.getWithToken({ id: videoUUID })
- const requiresAuth = videoDetails.privacy.id === VideoPrivacy.PRIVATE || videoDetails.privacy.id === VideoPrivacy.INTERNAL
-
- const privatePath = requiresAuth
- ? 'private/'
- : ''
- const token = requiresAuth
- ? server.accessToken
- : undefined
-
- const baseUrl = `http://${videoDetails.account.host}`
-
- expect(videoDetails.streamingPlaylists).to.have.lengthOf(1)
-
- const hlsPlaylist = videoDetails.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
- expect(hlsPlaylist).to.not.be.undefined
-
- const hlsFiles = hlsPlaylist.files
- expect(hlsFiles).to.have.lengthOf(resolutions.length)
-
- if (hlsOnly) expect(videoDetails.files).to.have.lengthOf(0)
- else expect(videoDetails.files).to.have.lengthOf(resolutions.length)
-
- // Check JSON files
- for (const resolution of resolutions) {
- const file = hlsFiles.find(f => f.resolution.id === resolution)
- expect(file).to.not.be.undefined
-
- if (file.resolution.id === VideoResolution.H_NOVIDEO) {
- expect(file.resolution.label).to.equal('Audio')
- } else {
- expect(file.resolution.label).to.equal(resolution + 'p')
- }
-
- expect(file.magnetUri).to.have.lengthOf.above(2)
- await checkWebTorrentWorks(file.magnetUri)
-
- {
- const nameReg = `${uuidRegex}-${file.resolution.id}`
-
- expect(file.torrentUrl).to.match(new RegExp(`${server.url}/lazy-static/torrents/${nameReg}-hls.torrent`))
-
- if (objectStorageBaseUrl && requiresAuth) {
- // eslint-disable-next-line max-len
- expect(file.fileUrl).to.match(new RegExp(`${server.url}/object-storage-proxy/streaming-playlists/hls/${privatePath}${videoDetails.uuid}/${nameReg}-fragmented.mp4`))
- } else if (objectStorageBaseUrl) {
- expectStartWith(file.fileUrl, objectStorageBaseUrl)
- } else {
- expect(file.fileUrl).to.match(
- new RegExp(`${baseUrl}/static/streaming-playlists/hls/${privatePath}${videoDetails.uuid}/${nameReg}-fragmented.mp4`)
- )
- }
- }
-
- {
- await Promise.all([
- makeRawRequest({ url: file.torrentUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.torrentDownloadUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.metadataUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.fileUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
-
- makeRawRequest({
- url: file.fileDownloadUrl,
- token,
- expectedStatus: objectStorageBaseUrl
- ? HttpStatusCode.FOUND_302
- : HttpStatusCode.OK_200
- })
- ])
- }
- }
-
- // Check master playlist
- {
- await checkResolutionsInMasterPlaylist({ server, token, playlistUrl: hlsPlaylist.playlistUrl, resolutions })
-
- const masterPlaylist = await server.streamingPlaylists.get({ url: hlsPlaylist.playlistUrl, token })
-
- let i = 0
- for (const resolution of resolutions) {
- expect(masterPlaylist).to.contain(`${resolution}.m3u8`)
- expect(masterPlaylist).to.contain(`${resolution}.m3u8`)
-
- const url = 'http://' + videoDetails.account.host
- await hlsInfohashExist(url, hlsPlaylist.playlistUrl, i)
-
- i++
- }
- }
-
- // Check resolution playlists
- {
- for (const resolution of resolutions) {
- const file = hlsFiles.find(f => f.resolution.id === resolution)
- const playlistName = removeFragmentedMP4Ext(basename(file.fileUrl)) + '.m3u8'
-
- let url: string
- if (objectStorageBaseUrl && requiresAuth) {
- url = `${baseUrl}/object-storage-proxy/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}`
- } else if (objectStorageBaseUrl) {
- url = `${objectStorageBaseUrl}hls/${videoUUID}/${playlistName}`
- } else {
- url = `${baseUrl}/static/streaming-playlists/hls/${privatePath}${videoUUID}/${playlistName}`
- }
-
- const subPlaylist = await server.streamingPlaylists.get({ url, token })
-
- expect(subPlaylist).to.match(new RegExp(`${uuidRegex}-${resolution}-fragmented.mp4`))
- expect(subPlaylist).to.contain(basename(file.fileUrl))
- }
- }
-
- {
- let baseUrlAndPath: string
- if (objectStorageBaseUrl && requiresAuth) {
- baseUrlAndPath = `${baseUrl}/object-storage-proxy/streaming-playlists/hls/${privatePath}${videoUUID}`
- } else if (objectStorageBaseUrl) {
- baseUrlAndPath = `${objectStorageBaseUrl}hls/${videoUUID}`
- } else {
- baseUrlAndPath = `${baseUrl}/static/streaming-playlists/hls/${privatePath}${videoUUID}`
- }
-
- for (const resolution of resolutions) {
- await checkSegmentHash({
- server,
- token,
- baseUrlPlaylist: baseUrlAndPath,
- baseUrlSegment: baseUrlAndPath,
- resolution,
- hlsPlaylist
- })
- }
- }
- }
-}
-
-async function checkVideoFileTokenReinjection (options: {
- server: PeerTubeServer
- videoUUID: string
- videoFileToken: string
- resolutions: number[]
- isLive: boolean
-}) {
- const { server, resolutions, videoFileToken, videoUUID, isLive } = options
-
- const video = await server.videos.getWithToken({ id: videoUUID })
- const hls = video.streamingPlaylists[0]
-
- const query = { videoFileToken, reinjectVideoFileToken: 'true' }
- const { text } = await makeRawRequest({ url: hls.playlistUrl, query, expectedStatus: HttpStatusCode.OK_200 })
-
- for (let i = 0; i < resolutions.length; i++) {
- const resolution = resolutions[i]
-
- const suffix = isLive
- ? i
- : `-${resolution}`
-
- expect(text).to.contain(`${suffix}.m3u8?videoFileToken=${videoFileToken}&reinjectVideoFileToken=true`)
- }
-
- const resolutionPlaylists = extractResolutionPlaylistUrls(hls.playlistUrl, text)
- expect(resolutionPlaylists).to.have.lengthOf(resolutions.length)
-
- for (const url of resolutionPlaylists) {
- const { text } = await makeRawRequest({ url, query, expectedStatus: HttpStatusCode.OK_200 })
-
- const extension = isLive
- ? '.ts'
- : '.mp4'
-
- expect(text).to.contain(`${extension}?videoFileToken=${videoFileToken}`)
- expect(text).not.to.contain(`reinjectVideoFileToken=true`)
- }
-}
-
-function extractResolutionPlaylistUrls (masterPath: string, masterContent: string) {
- return masterContent.match(/^([^.]+\.m3u8.*)/mg)
- .map(filename => join(dirname(masterPath), filename))
-}
-
-export {
- checkSegmentHash,
- checkLiveSegmentHash,
- checkResolutionsInMasterPlaylist,
- completeCheckHlsPlaylist,
- extractResolutionPlaylistUrls,
- checkVideoFileTokenReinjection
-}
diff --git a/server/tests/shared/tests.ts b/server/tests/shared/tests.ts
deleted file mode 100644
index d2cb040fb..000000000
--- a/server/tests/shared/tests.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-const FIXTURE_URLS = {
- peertube_long: 'https://peertube2.cpy.re/videos/watch/122d093a-1ede-43bd-bd34-59d2931ffc5e',
- peertube_short: 'https://peertube2.cpy.re/w/3fbif9S3WmtTP8gGsC5HBd',
-
- youtube: 'https://www.youtube.com/watch?v=msX3jv1XdvM',
-
- /**
- * The video is used to check format-selection correctness wrt. HDR,
- * which brings its own set of oddities outside of a MediaSource.
- *
- * The video needs to have the following format_ids:
- * (which you can check by using `youtube-dl -F`):
- * - (webm vp9)
- * - (mp4 avc1)
- * - (webm vp9.2 HDR)
- */
- youtubeHDR: 'https://www.youtube.com/watch?v=RQgnBB9z_N4',
-
- youtubeChannel: 'https://youtube.com/channel/UCtnlZdXv3-xQzxiqfn6cjIA',
- youtubePlaylist: 'https://youtube.com/playlist?list=PLRGXHPrcPd2yc2KdswlAWOxIJ8G3vgy4h',
-
- // eslint-disable-next-line max-len
- magnet: 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4',
-
- badVideo: 'https://download.cpy.re/peertube/bad_video.mp4',
- goodVideo: 'https://download.cpy.re/peertube/good_video.mp4',
- goodVideo720: 'https://download.cpy.re/peertube/good_video_720.mp4',
-
- file4K: 'https://download.cpy.re/peertube/4k_file.txt'
-}
-
-function buildRequestStub (): any {
- return { }
-}
-
-export {
- FIXTURE_URLS,
-
- buildRequestStub
-}
diff --git a/server/tests/shared/tracker.ts b/server/tests/shared/tracker.ts
deleted file mode 100644
index 9c1f0246a..000000000
--- a/server/tests/shared/tracker.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { expect } from 'chai'
-import { sha1 } from '@shared/extra-utils'
-import { makeGetRequest } from '@shared/server-commands'
-
-async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, fileNumber: number) {
- const path = '/tracker/announce'
-
- const infohash = sha1(`2${masterPlaylistUrl}+V${fileNumber}`)
-
- // From bittorrent-tracker
- const infohashBinary = escape(Buffer.from(infohash, 'hex').toString('binary')).replace(/[@*/+]/g, function (char) {
- return '%' + char.charCodeAt(0).toString(16).toUpperCase()
- })
-
- const res = await makeGetRequest({
- url: serverUrl,
- path,
- rawQuery: `peer_id=-WW0105-NkvYO/egUAr4&info_hash=${infohashBinary}&port=42100`,
- expectedStatus: 200
- })
-
- expect(res.text).to.not.contain('failure')
-}
-
-export {
- hlsInfohashExist
-}
diff --git a/server/tests/shared/video-playlists.ts b/server/tests/shared/video-playlists.ts
deleted file mode 100644
index 8db303fd8..000000000
--- a/server/tests/shared/video-playlists.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { expect } from 'chai'
-import { readdir } from 'fs-extra'
-import { PeerTubeServer } from '@shared/server-commands'
-
-async function checkPlaylistFilesWereRemoved (
- playlistUUID: string,
- server: PeerTubeServer,
- directories = [ 'thumbnails' ]
-) {
- for (const directory of directories) {
- const directoryPath = server.getDirectoryPath(directory)
-
- const files = await readdir(directoryPath)
- for (const file of files) {
- expect(file).to.not.contain(playlistUUID)
- }
- }
-}
-
-export {
- checkPlaylistFilesWereRemoved
-}
diff --git a/server/tests/shared/videos.ts b/server/tests/shared/videos.ts
deleted file mode 100644
index ac24bb173..000000000
--- a/server/tests/shared/videos.ts
+++ /dev/null
@@ -1,315 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { basename, join } from 'path'
-import { loadLanguages, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '@server/initializers/constants'
-import { getLowercaseExtension, pick, uuidRegex } from '@shared/core-utils'
-import { HttpStatusCode, VideoCaption, VideoDetails, VideoPrivacy, VideoResolution } from '@shared/models'
-import { makeRawRequest, PeerTubeServer, VideoEdit, waitJobs } from '@shared/server-commands'
-import { dateIsValid, expectStartWith, testImageGeneratedByFFmpeg } from './checks'
-import { checkWebTorrentWorks } from './webtorrent'
-
-loadLanguages()
-
-async function completeWebVideoFilesCheck (options: {
- server: PeerTubeServer
- originServer: PeerTubeServer
- videoUUID: string
- fixture: string
- files: {
- resolution: number
- size?: number
- }[]
- objectStorageBaseUrl?: string
-}) {
- const { originServer, server, videoUUID, files, fixture, objectStorageBaseUrl } = options
- const video = await server.videos.getWithToken({ id: videoUUID })
- const serverConfig = await originServer.config.getConfig()
- const requiresAuth = video.privacy.id === VideoPrivacy.PRIVATE || video.privacy.id === VideoPrivacy.INTERNAL
-
- const transcodingEnabled = serverConfig.transcoding.web_videos.enabled
-
- for (const attributeFile of files) {
- const file = video.files.find(f => f.resolution.id === attributeFile.resolution)
- expect(file, `resolution ${attributeFile.resolution} does not exist`).not.to.be.undefined
-
- let extension = getLowercaseExtension(fixture)
- // Transcoding enabled: extension will always be .mp4
- if (transcodingEnabled) extension = '.mp4'
-
- expect(file.id).to.exist
- expect(file.magnetUri).to.have.lengthOf.above(2)
-
- {
- const privatePath = requiresAuth
- ? 'private/'
- : ''
- const nameReg = `${uuidRegex}-${file.resolution.id}`
-
- expect(file.torrentDownloadUrl).to.match(new RegExp(`${server.url}/download/torrents/${nameReg}.torrent`))
- expect(file.torrentUrl).to.match(new RegExp(`${server.url}/lazy-static/torrents/${nameReg}.torrent`))
-
- if (objectStorageBaseUrl && requiresAuth) {
- const regexp = new RegExp(`${originServer.url}/object-storage-proxy/web-videos/${privatePath}${nameReg}${extension}`)
- expect(file.fileUrl).to.match(regexp)
- } else if (objectStorageBaseUrl) {
- expectStartWith(file.fileUrl, objectStorageBaseUrl)
- } else {
- expect(file.fileUrl).to.match(new RegExp(`${originServer.url}/static/web-videos/${privatePath}${nameReg}${extension}`))
- }
-
- expect(file.fileDownloadUrl).to.match(new RegExp(`${originServer.url}/download/videos/${nameReg}${extension}`))
- }
-
- {
- const token = requiresAuth
- ? server.accessToken
- : undefined
-
- await Promise.all([
- makeRawRequest({ url: file.torrentUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.torrentDownloadUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.metadataUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({ url: file.fileUrl, token, expectedStatus: HttpStatusCode.OK_200 }),
- makeRawRequest({
- url: file.fileDownloadUrl,
- token,
- expectedStatus: objectStorageBaseUrl ? HttpStatusCode.FOUND_302 : HttpStatusCode.OK_200
- })
- ])
- }
-
- expect(file.resolution.id).to.equal(attributeFile.resolution)
-
- if (file.resolution.id === VideoResolution.H_NOVIDEO) {
- expect(file.resolution.label).to.equal('Audio')
- } else {
- expect(file.resolution.label).to.equal(attributeFile.resolution + 'p')
- }
-
- if (attributeFile.size) {
- const minSize = attributeFile.size - ((10 * attributeFile.size) / 100)
- const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100)
- expect(
- file.size,
- 'File size for resolution ' + file.resolution.label + ' outside confidence interval (' + minSize + '> size <' + maxSize + ')'
- ).to.be.above(minSize).and.below(maxSize)
- }
-
- await checkWebTorrentWorks(file.magnetUri)
- }
-}
-
-async function completeVideoCheck (options: {
- server: PeerTubeServer
- originServer: PeerTubeServer
- videoUUID: string
- attributes: {
- name: string
- category: number
- licence: number
- language: string
- nsfw: boolean
- commentsEnabled: boolean
- downloadEnabled: boolean
- description: string
- publishedAt?: string
- support: string
- originallyPublishedAt?: string
- account: {
- name: string
- host: string
- }
- isLocal: boolean
- tags: string[]
- privacy: number
- likes?: number
- dislikes?: number
- duration: number
- channel: {
- displayName: string
- name: string
- description: string
- isLocal: boolean
- }
- fixture: string
- files: {
- resolution: number
- size: number
- }[]
- thumbnailfile?: string
- previewfile?: string
- }
-}) {
- const { attributes, originServer, server, videoUUID } = options
-
- const video = await server.videos.get({ id: videoUUID })
-
- if (!attributes.likes) attributes.likes = 0
- if (!attributes.dislikes) attributes.dislikes = 0
-
- expect(video.name).to.equal(attributes.name)
- expect(video.category.id).to.equal(attributes.category)
- expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Unknown')
- expect(video.licence.id).to.equal(attributes.licence)
- expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown')
- expect(video.language.id).to.equal(attributes.language)
- expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown')
- expect(video.privacy.id).to.deep.equal(attributes.privacy)
- expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
- expect(video.nsfw).to.equal(attributes.nsfw)
- expect(video.description).to.equal(attributes.description)
- expect(video.account.id).to.be.a('number')
- expect(video.account.host).to.equal(attributes.account.host)
- expect(video.account.name).to.equal(attributes.account.name)
- expect(video.channel.displayName).to.equal(attributes.channel.displayName)
- expect(video.channel.name).to.equal(attributes.channel.name)
- expect(video.likes).to.equal(attributes.likes)
- expect(video.dislikes).to.equal(attributes.dislikes)
- expect(video.isLocal).to.equal(attributes.isLocal)
- expect(video.duration).to.equal(attributes.duration)
- expect(video.url).to.contain(originServer.host)
- expect(dateIsValid(video.createdAt)).to.be.true
- expect(dateIsValid(video.publishedAt)).to.be.true
- expect(dateIsValid(video.updatedAt)).to.be.true
-
- if (attributes.publishedAt) {
- expect(video.publishedAt).to.equal(attributes.publishedAt)
- }
-
- if (attributes.originallyPublishedAt) {
- expect(video.originallyPublishedAt).to.equal(attributes.originallyPublishedAt)
- } else {
- expect(video.originallyPublishedAt).to.be.null
- }
-
- expect(video.files).to.have.lengthOf(attributes.files.length)
- expect(video.tags).to.deep.equal(attributes.tags)
- expect(video.account.name).to.equal(attributes.account.name)
- expect(video.account.host).to.equal(attributes.account.host)
- expect(video.channel.displayName).to.equal(attributes.channel.displayName)
- expect(video.channel.name).to.equal(attributes.channel.name)
- expect(video.channel.host).to.equal(attributes.account.host)
- expect(video.channel.isLocal).to.equal(attributes.channel.isLocal)
- expect(dateIsValid(video.channel.createdAt.toString())).to.be.true
- expect(dateIsValid(video.channel.updatedAt.toString())).to.be.true
- expect(video.commentsEnabled).to.equal(attributes.commentsEnabled)
- expect(video.downloadEnabled).to.equal(attributes.downloadEnabled)
-
- expect(video.thumbnailPath).to.exist
- await testImageGeneratedByFFmpeg(server.url, attributes.thumbnailfile || attributes.fixture, video.thumbnailPath)
-
- if (attributes.previewfile) {
- expect(video.previewPath).to.exist
- await testImageGeneratedByFFmpeg(server.url, attributes.previewfile, video.previewPath)
- }
-
- await completeWebVideoFilesCheck({ server, originServer, videoUUID: video.uuid, ...pick(attributes, [ 'fixture', 'files' ]) })
-}
-
-async function checkVideoFilesWereRemoved (options: {
- server: PeerTubeServer
- video: VideoDetails
- captions?: VideoCaption[]
- onlyVideoFiles?: boolean // default false
-}) {
- const { video, server, captions = [], onlyVideoFiles = false } = options
-
- const webVideoFiles = video.files || []
- const hlsFiles = video.streamingPlaylists[0]?.files || []
-
- const thumbnailName = basename(video.thumbnailPath)
- const previewName = basename(video.previewPath)
-
- const torrentNames = webVideoFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
-
- const captionNames = captions.map(c => basename(c.captionPath))
-
- const webVideoFilenames = webVideoFiles.map(f => basename(f.fileUrl))
- const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
-
- let directories: { [ directory: string ]: string[] } = {
- videos: webVideoFilenames,
- redundancy: webVideoFilenames,
- [join('playlists', 'hls')]: hlsFilenames,
- [join('redundancy', 'hls')]: hlsFilenames
- }
-
- if (onlyVideoFiles !== true) {
- directories = {
- ...directories,
-
- thumbnails: [ thumbnailName ],
- previews: [ previewName ],
- torrents: torrentNames,
- captions: captionNames
- }
- }
-
- for (const directory of Object.keys(directories)) {
- const directoryPath = server.servers.buildDirectory(directory)
-
- const directoryExists = await pathExists(directoryPath)
- if (directoryExists === false) continue
-
- const existingFiles = await readdir(directoryPath)
- for (const existingFile of existingFiles) {
- for (const shouldNotExist of directories[directory]) {
- expect(existingFile, `File ${existingFile} should not exist in ${directoryPath}`).to.not.contain(shouldNotExist)
- }
- }
- }
-}
-
-async function saveVideoInServers (servers: PeerTubeServer[], uuid: string) {
- for (const server of servers) {
- server.store.videoDetails = await server.videos.get({ id: uuid })
- }
-}
-
-function checkUploadVideoParam (options: {
- server: PeerTubeServer
- token: string
- attributes: Partial
- expectedStatus?: HttpStatusCode
- completedExpectedStatus?: HttpStatusCode
- mode?: 'legacy' | 'resumable'
-}) {
- const { server, token, attributes, completedExpectedStatus, expectedStatus, mode = 'legacy' } = options
-
- return mode === 'legacy'
- ? server.videos.buildLegacyUpload({ token, attributes, expectedStatus: expectedStatus || completedExpectedStatus })
- : server.videos.buildResumeUpload({
- token,
- attributes,
- expectedStatus,
- completedExpectedStatus,
- path: '/api/v1/videos/upload-resumable'
- })
-}
-
-// serverNumber starts from 1
-async function uploadRandomVideoOnServers (
- servers: PeerTubeServer[],
- serverNumber: number,
- additionalParams?: VideoEdit & { prefixName?: string }
-) {
- const server = servers.find(s => s.serverNumber === serverNumber)
- const res = await server.videos.randomUpload({ wait: false, additionalParams })
-
- await waitJobs(servers)
-
- return res
-}
-
-// ---------------------------------------------------------------------------
-
-export {
- completeVideoCheck,
- completeWebVideoFilesCheck,
- checkUploadVideoParam,
- uploadRandomVideoOnServers,
- checkVideoFilesWereRemoved,
- saveVideoInServers
-}
diff --git a/server/tests/shared/views.ts b/server/tests/shared/views.ts
deleted file mode 100644
index e6b289715..000000000
--- a/server/tests/shared/views.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { FfmpegCommand } from 'fluent-ffmpeg'
-import { wait } from '@shared/core-utils'
-import { VideoCreateResult, VideoPrivacy } from '@shared/models'
-import {
- createMultipleServers,
- doubleFollow,
- PeerTubeServer,
- setAccessTokensToServers,
- setDefaultVideoChannel,
- waitJobs,
- waitUntilLivePublishedOnAllServers
-} from '@shared/server-commands'
-
-async function processViewersStats (servers: PeerTubeServer[]) {
- await wait(6000)
-
- for (const server of servers) {
- await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } })
- await server.debug.sendCommand({ body: { command: 'process-video-viewers' } })
- }
-
- await waitJobs(servers)
-}
-
-async function processViewsBuffer (servers: PeerTubeServer[]) {
- for (const server of servers) {
- await server.debug.sendCommand({ body: { command: 'process-video-views-buffer' } })
- }
-
- await waitJobs(servers)
-}
-
-async function prepareViewsServers () {
- const servers = await createMultipleServers(2)
- await setAccessTokensToServers(servers)
- await setDefaultVideoChannel(servers)
-
- await servers[0].config.updateCustomSubConfig({
- newConfig: {
- live: {
- enabled: true,
- allowReplay: true,
- transcoding: {
- enabled: false
- }
- }
- }
- })
-
- await doubleFollow(servers[0], servers[1])
-
- return servers
-}
-
-async function prepareViewsVideos (options: {
- servers: PeerTubeServer[]
- live: boolean
- vod: boolean
-}) {
- const { servers } = options
-
- const liveAttributes = {
- name: 'live video',
- channelId: servers[0].store.channel.id,
- privacy: VideoPrivacy.PUBLIC
- }
-
- let ffmpegCommand: FfmpegCommand
- let live: VideoCreateResult
- let vod: VideoCreateResult
-
- if (options.live) {
- live = await servers[0].live.create({ fields: liveAttributes })
-
- ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: live.uuid })
- await waitUntilLivePublishedOnAllServers(servers, live.uuid)
- }
-
- if (options.vod) {
- vod = await servers[0].videos.quickUpload({ name: 'video' })
- }
-
- await waitJobs(servers)
-
- return { liveVideoId: live?.uuid, vodVideoId: vod?.uuid, ffmpegCommand }
-}
-
-export {
- processViewersStats,
- prepareViewsServers,
- processViewsBuffer,
- prepareViewsVideos
-}
diff --git a/server/tests/shared/webtorrent.ts b/server/tests/shared/webtorrent.ts
deleted file mode 100644
index d5bd86500..000000000
--- a/server/tests/shared/webtorrent.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { expect } from 'chai'
-import { readFile } from 'fs-extra'
-import parseTorrent from 'parse-torrent'
-import { basename, join } from 'path'
-import * as WebTorrent from 'webtorrent'
-import { VideoFile } from '@shared/models'
-import { PeerTubeServer } from '@shared/server-commands'
-
-let webtorrent: WebTorrent.Instance
-
-export async function checkWebTorrentWorks (magnetUri: string, pathMatch?: RegExp) {
- const torrent = await webtorrentAdd(magnetUri, true)
-
- expect(torrent.files).to.be.an('array')
- expect(torrent.files.length).to.equal(1)
- expect(torrent.files[0].path).to.exist.and.to.not.equal('')
-
- if (pathMatch) {
- expect(torrent.files[0].path).match(pathMatch)
- }
-}
-
-export async function parseTorrentVideo (server: PeerTubeServer, file: VideoFile) {
- const torrentName = basename(file.torrentUrl)
- const torrentPath = server.servers.buildDirectory(join('torrents', torrentName))
-
- const data = await readFile(torrentPath)
-
- return parseTorrent(data)
-}
-
-// ---------------------------------------------------------------------------
-// Private
-// ---------------------------------------------------------------------------
-
-function webtorrentAdd (torrentId: string, refreshWebTorrent = false) {
- const WebTorrent = require('webtorrent')
-
- if (webtorrent && refreshWebTorrent) webtorrent.destroy()
- if (!webtorrent || refreshWebTorrent) webtorrent = new WebTorrent()
-
- webtorrent.on('error', err => console.error('Error in webtorrent', err))
-
- return new Promise(res => {
- const torrent = webtorrent.add(torrentId, res)
-
- torrent.on('error', err => console.error('Error in webtorrent torrent', err))
- torrent.on('warning', warn => {
- const msg = typeof warn === 'string'
- ? warn
- : warn.message
-
- if (msg.includes('Unsupported')) return
-
- console.error('Warning in webtorrent torrent', warn)
- })
- })
-}
--
cgit v1.2.3