aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/videos
diff options
context:
space:
mode:
authorFlorent <florent.git@zeteo.me>2022-08-10 09:53:39 +0200
committerGitHub <noreply@github.com>2022-08-10 09:53:39 +0200
commit2a491182e483b97afb1b65c908b23cb48d591807 (patch)
treeec13503216ad72a3ea8f1ce3b659899f8167fb47 /server/tests/api/videos
parent06ac128958c489efe1008eeca1df683819bd2f18 (diff)
downloadPeerTube-2a491182e483b97afb1b65c908b23cb48d591807.tar.gz
PeerTube-2a491182e483b97afb1b65c908b23cb48d591807.tar.zst
PeerTube-2a491182e483b97afb1b65c908b23cb48d591807.zip
Channel sync (#5135)
* Add external channel URL for channel update / creation (#754) * Disallow synchronisation if user has no video quota (#754) * More constraints serverside (#754) * Disable sync if server configuration does not allow HTTP import (#754) * Working version synchronizing videos with a job (#754) TODO: refactoring, too much code duplication * More logs and try/catch (#754) * Fix eslint error (#754) * WIP: support synchronization time change (#754) * New frontend #754 * WIP: Create sync front (#754) * Enhance UI, sync creation form (#754) * Warning message when HTTP upload is disallowed * More consistent names (#754) * Binding Front with API (#754) * Add a /me API (#754) * Improve list UI (#754) * Implement creation and deletion routes (#754) * Lint (#754) * Lint again (#754) * WIP: UI for triggering import existing videos (#754) * Implement jobs for syncing and importing channels * Don't sync videos before sync creation + avoid concurrency issue (#754) * Cleanup (#754) * Cleanup: OpenAPI + API rework (#754) * Remove dead code (#754) * Eslint (#754) * Revert the mess with whitespaces in constants.ts (#754) * Some fixes after rebase (#754) * Several fixes after PR remarks (#754) * Front + API: Rename video-channels-sync to video-channel-syncs (#754) * Allow enabling channel sync through UI (#754) * getChannelInfo (#754) * Minor fixes: openapi + model + sql (#754) * Simplified API validators (#754) * Rename MChannelSync to MChannelSyncChannel (#754) * Add command for VideoChannelSync (#754) * Use synchronization.enabled config (#754) * Check parameters test + some fixes (#754) * Fix conflict mistake (#754) * Restrict access to video channel sync list API (#754) * Start adding unit test for synchronization (#754) * Continue testing (#754) * Tests finished + convertion of job to scheduler (#754) * Add lastSyncAt field (#754) * Fix externalRemoteUrl sort + creation date not well formatted (#754) * Small fix (#754) * Factorize addYoutubeDLImport and buildVideo (#754) * Check duplicates on channel not on users (#754) * factorize thumbnail generation (#754) * Fetch error should return status 400 (#754) * Separate video-channel-import and video-channel-sync-latest (#754) * Bump DB migration version after rebase (#754) * Prettier states in UI table (#754) * Add DefaultScope in VideoChannelSyncModel (#754) * Fix audit logs (#754) * Ensure user can upload when importing channel + minor fixes (#754) * Mark synchronization as failed on exception + typos (#754) * Change REST API for importing videos into channel (#754) * Add option for fully synchronize a chnanel (#754) * Return a whole sync object on creation to avoid tricks in Front (#754) * Various remarks (#754) * Single quotes by default (#754) * Rename synchronization to video_channel_synchronization * Add check.latest_videos_count and max_per_user options (#754) * Better channel rendering in list #754 * Allow sorting with channel name and state (#754) * Add missing tests for channel imports (#754) * Prefer using a parent job for channel sync * Styling * Client styling Co-authored-by: Chocobozzz <me@florianbigard.com>
Diffstat (limited to 'server/tests/api/videos')
-rw-r--r--server/tests/api/videos/channel-import-videos.ts50
-rw-r--r--server/tests/api/videos/index.ts2
-rw-r--r--server/tests/api/videos/video-channel-syncs.ts226
-rw-r--r--server/tests/api/videos/video-imports.ts22
4 files changed, 282 insertions, 18 deletions
diff --git a/server/tests/api/videos/channel-import-videos.ts b/server/tests/api/videos/channel-import-videos.ts
new file mode 100644
index 000000000..f7540e1ba
--- /dev/null
+++ b/server/tests/api/videos/channel-import-videos.ts
@@ -0,0 +1,50 @@
1import { expect } from 'chai'
2import { FIXTURE_URLS } from '@server/tests/shared'
3import { areHttpImportTestsDisabled } from '@shared/core-utils'
4import {
5 createSingleServer,
6 getServerImportConfig,
7 PeerTubeServer,
8 setAccessTokensToServers,
9 setDefaultVideoChannel,
10 waitJobs
11} from '@shared/server-commands'
12
13describe('Test videos import in a channel', function () {
14 if (areHttpImportTestsDisabled()) return
15
16 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
17
18 describe('Import using ' + mode, function () {
19 let server: PeerTubeServer
20
21 before(async function () {
22 this.timeout(120_000)
23
24 server = await createSingleServer(1, getServerImportConfig(mode))
25
26 await setAccessTokensToServers([ server ])
27 await setDefaultVideoChannel([ server ])
28
29 await server.config.enableChannelSync()
30 })
31
32 it('Should import a whole channel', async function () {
33 this.timeout(240_000)
34
35 await server.channels.importVideos({ channelName: server.store.channel.name, externalChannelUrl: FIXTURE_URLS.youtubeChannel })
36 await waitJobs(server)
37
38 const videos = await server.videos.listByChannel({ handle: server.store.channel.name })
39 expect(videos.total).to.equal(2)
40 })
41
42 after(async function () {
43 await server?.kill()
44 })
45 })
46 }
47
48 runSuite('yt-dlp')
49 runSuite('youtube-dl')
50})
diff --git a/server/tests/api/videos/index.ts b/server/tests/api/videos/index.ts
index a0b6b01cf..266155297 100644
--- a/server/tests/api/videos/index.ts
+++ b/server/tests/api/videos/index.ts
@@ -4,6 +4,8 @@ import './single-server'
4import './video-captions' 4import './video-captions'
5import './video-change-ownership' 5import './video-change-ownership'
6import './video-channels' 6import './video-channels'
7import './channel-import-videos'
8import './video-channel-syncs'
7import './video-comments' 9import './video-comments'
8import './video-description' 10import './video-description'
9import './video-files' 11import './video-files'
diff --git a/server/tests/api/videos/video-channel-syncs.ts b/server/tests/api/videos/video-channel-syncs.ts
new file mode 100644
index 000000000..229c01f68
--- /dev/null
+++ b/server/tests/api/videos/video-channel-syncs.ts
@@ -0,0 +1,226 @@
1import 'mocha'
2import { expect } from 'chai'
3import { FIXTURE_URLS } from '@server/tests/shared'
4import { areHttpImportTestsDisabled } from '@shared/core-utils'
5import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
6import {
7 ChannelSyncsCommand,
8 createSingleServer,
9 getServerImportConfig,
10 PeerTubeServer,
11 setAccessTokensToServers,
12 setDefaultAccountAvatar,
13 setDefaultChannelAvatar,
14 setDefaultVideoChannel,
15 waitJobs
16} from '@shared/server-commands'
17
18describe('Test channel synchronizations', function () {
19 if (areHttpImportTestsDisabled()) return
20
21 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
22
23 describe('Sync using ' + mode, function () {
24 let server: PeerTubeServer
25 let command: ChannelSyncsCommand
26 let startTestDate: Date
27 const userInfo = {
28 accessToken: '',
29 username: 'user1',
30 channelName: 'user1_channel',
31 channelId: -1,
32 syncId: -1
33 }
34
35 async function changeDateForSync (channelSyncId: number, newDate: string) {
36 await server.sql.updateQuery(
37 `UPDATE "videoChannelSync" ` +
38 `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
39 `WHERE id=${channelSyncId}`
40 )
41 }
42
43 before(async function () {
44 this.timeout(120_000)
45
46 startTestDate = new Date()
47
48 server = await createSingleServer(1, getServerImportConfig(mode))
49
50 await setAccessTokensToServers([ server ])
51 await setDefaultVideoChannel([ server ])
52 await setDefaultChannelAvatar([ server ])
53 await setDefaultAccountAvatar([ server ])
54
55 await server.config.enableChannelSync()
56
57 command = server.channelSyncs
58
59 {
60 userInfo.accessToken = await server.users.generateUserAndToken(userInfo.username)
61
62 const { videoChannels } = await server.users.getMyInfo({ token: userInfo.accessToken })
63 userInfo.channelId = videoChannels[0].id
64 }
65 })
66
67 it('Should fetch the latest channel videos of a remote channel', async function () {
68 this.timeout(120_000)
69
70 {
71 const { video } = await server.imports.importVideo({
72 attributes: {
73 channelId: server.store.channel.id,
74 privacy: VideoPrivacy.PUBLIC,
75 targetUrl: FIXTURE_URLS.youtube
76 }
77 })
78
79 expect(video.name).to.equal('small video - youtube')
80
81 const { total } = await server.videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
82 expect(total).to.equal(1)
83 }
84
85 const { videoChannelSync } = await command.create({
86 attributes: {
87 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
88 videoChannelId: server.store.channel.id
89 },
90 token: server.accessToken,
91 expectedStatus: HttpStatusCode.OK_200
92 })
93
94 // Ensure any missing video not already fetched will be considered as new
95 await changeDateForSync(videoChannelSync.id, '1970-01-01')
96
97 await server.debug.sendCommand({
98 body: {
99 command: 'process-video-channel-sync-latest'
100 }
101 })
102
103 {
104 await waitJobs(server)
105
106 const { total, data } = await server.videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
107 expect(total).to.equal(2)
108 expect(data[0].name).to.equal('test')
109 }
110 })
111
112 it('Should add another synchronization', async function () {
113 const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
114
115 const { videoChannelSync } = await command.create({
116 attributes: {
117 externalChannelUrl,
118 videoChannelId: server.store.channel.id
119 },
120 token: server.accessToken,
121 expectedStatus: HttpStatusCode.OK_200
122 })
123
124 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
125 expect(videoChannelSync.channel).to.include({
126 id: server.store.channel.id,
127 name: 'root_channel'
128 })
129 expect(videoChannelSync.state.id).to.equal(VideoChannelSyncState.WAITING_FIRST_RUN)
130 expect(new Date(videoChannelSync.createdAt)).to.be.above(startTestDate).and.to.be.at.most(new Date())
131 })
132
133 it('Should add a synchronization for another user', async function () {
134 const { videoChannelSync } = await command.create({
135 attributes: {
136 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
137 videoChannelId: userInfo.channelId
138 },
139 token: userInfo.accessToken
140 })
141 userInfo.syncId = videoChannelSync.id
142 })
143
144 it('Should not import a channel if not asked', async function () {
145 await waitJobs(server)
146
147 const { data } = await command.listByAccount({ accountName: userInfo.username })
148
149 expect(data[0].state).to.contain({
150 id: VideoChannelSyncState.WAITING_FIRST_RUN,
151 label: 'Waiting first run'
152 })
153 })
154
155 it('Should only fetch the videos newer than the creation date', async function () {
156 this.timeout(120_000)
157
158 await changeDateForSync(userInfo.syncId, '2019-03-01')
159
160 await server.debug.sendCommand({
161 body: {
162 command: 'process-video-channel-sync-latest'
163 }
164 })
165
166 await waitJobs(server)
167
168 const { data, total } = await server.videos.listByChannel({
169 handle: userInfo.channelName,
170 include: VideoInclude.NOT_PUBLISHED_STATE
171 })
172
173 expect(total).to.equal(1)
174 expect(data[0].name).to.equal('test')
175 })
176
177 it('Should list channel synchronizations', async function () {
178 // Root
179 {
180 const { total, data } = await command.listByAccount({ accountName: 'root' })
181 expect(total).to.equal(2)
182
183 expect(data[0]).to.deep.contain({
184 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
185 state: {
186 id: VideoChannelSyncState.SYNCED,
187 label: 'Synchronized'
188 }
189 })
190
191 expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
192
193 expect(data[0].channel).to.contain({ id: server.store.channel.id })
194 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
195 }
196
197 // User
198 {
199 const { total, data } = await command.listByAccount({ accountName: userInfo.username })
200 expect(total).to.equal(1)
201 expect(data[0]).to.deep.contain({
202 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
203 state: {
204 id: VideoChannelSyncState.SYNCED,
205 label: 'Synchronized'
206 }
207 })
208 }
209 })
210
211 it('Should remove user\'s channel synchronizations', async function () {
212 await command.delete({ channelSyncId: userInfo.syncId })
213
214 const { total } = await command.listByAccount({ accountName: userInfo.username })
215 expect(total).to.equal(0)
216 })
217
218 after(async function () {
219 await server?.kill()
220 })
221 })
222 }
223
224 runSuite('youtube-dl')
225 runSuite('yt-dlp')
226})
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts
index 603e2d234..a487062a2 100644
--- a/server/tests/api/videos/video-imports.ts
+++ b/server/tests/api/videos/video-imports.ts
@@ -12,6 +12,7 @@ import {
12 createMultipleServers, 12 createMultipleServers,
13 createSingleServer, 13 createSingleServer,
14 doubleFollow, 14 doubleFollow,
15 getServerImportConfig,
15 PeerTubeServer, 16 PeerTubeServer,
16 setAccessTokensToServers, 17 setAccessTokensToServers,
17 setDefaultVideoChannel, 18 setDefaultVideoChannel,
@@ -84,24 +85,9 @@ describe('Test video imports', function () {
84 let servers: PeerTubeServer[] = [] 85 let servers: PeerTubeServer[] = []
85 86
86 before(async function () { 87 before(async function () {
87 this.timeout(30_000) 88 this.timeout(60_000)
88 89
89 // Run servers 90 servers = await createMultipleServers(2, getServerImportConfig(mode))
90 servers = await createMultipleServers(2, {
91 import: {
92 videos: {
93 http: {
94 youtube_dl_release: {
95 url: mode === 'youtube-dl'
96 ? 'https://yt-dl.org/downloads/latest/youtube-dl'
97 : 'https://api.github.com/repos/yt-dlp/yt-dlp/releases',
98
99 name: mode
100 }
101 }
102 }
103 }
104 })
105 91
106 await setAccessTokensToServers(servers) 92 await setAccessTokensToServers(servers)
107 await setDefaultVideoChannel(servers) 93 await setDefaultVideoChannel(servers)