1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } from 'chai'
4 import { FIXTURE_URLS } from '@server/tests/shared'
5 import { areHttpImportTestsDisabled } from '@shared/core-utils'
6 import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
12 setAccessTokensToServers,
13 setDefaultAccountAvatar,
14 setDefaultChannelAvatar,
15 setDefaultVideoChannel,
17 } from '@shared/server-commands'
19 describe('Test channel synchronizations', function () {
20 if (areHttpImportTestsDisabled()) return
22 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
24 describe('Sync using ' + mode, function () {
25 let servers: PeerTubeServer[]
27 let startTestDate: Date
29 let rootChannelSyncId: number
33 channelName: 'user1_channel',
38 async function changeDateForSync (channelSyncId: number, newDate: string) {
39 await servers[0].sql.updateQuery(
40 `UPDATE "videoChannelSync" ` +
41 `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
42 `WHERE id=${channelSyncId}`
46 before(async function () {
49 startTestDate = new Date()
51 servers = await createMultipleServers(2, getServerImportConfig(mode))
53 await setAccessTokensToServers(servers)
54 await setDefaultVideoChannel(servers)
55 await setDefaultChannelAvatar(servers)
56 await setDefaultAccountAvatar(servers)
58 await servers[0].config.enableChannelSync()
61 userInfo.accessToken = await servers[0].users.generateUserAndToken(userInfo.username)
63 const { videoChannels } = await servers[0].users.getMyInfo({ token: userInfo.accessToken })
64 userInfo.channelId = videoChannels[0].id
68 it('Should fetch the latest channel videos of a remote channel', async function () {
72 const { video } = await servers[0].imports.importVideo({
74 channelId: servers[0].store.channel.id,
75 privacy: VideoPrivacy.PUBLIC,
76 targetUrl: FIXTURE_URLS.youtube
80 expect(video.name).to.equal('small video - youtube')
81 expect(video.waitTranscoding).to.be.true
83 const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
84 expect(total).to.equal(1)
87 const { videoChannelSync } = await servers[0].channelSyncs.create({
89 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
90 videoChannelId: servers[0].store.channel.id
92 token: servers[0].accessToken,
93 expectedStatus: HttpStatusCode.OK_200
95 rootChannelSyncId = videoChannelSync.id
97 // Ensure any missing video not already fetched will be considered as new
98 await changeDateForSync(videoChannelSync.id, '1970-01-01')
100 await servers[0].debug.sendCommand({
102 command: 'process-video-channel-sync-latest'
107 await waitJobs(servers)
109 const { total, data } = await servers[0].videos.listByChannel({
110 handle: 'root_channel',
111 include: VideoInclude.NOT_PUBLISHED_STATE
113 expect(total).to.equal(2)
114 expect(data[0].name).to.equal('test')
115 expect(data[0].waitTranscoding).to.be.true
119 it('Should add another synchronization', async function () {
120 const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
122 const { videoChannelSync } = await servers[0].channelSyncs.create({
125 videoChannelId: servers[0].store.channel.id
127 token: servers[0].accessToken,
128 expectedStatus: HttpStatusCode.OK_200
131 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
132 expect(videoChannelSync.channel).to.include({
133 id: servers[0].store.channel.id,
136 expect(videoChannelSync.state.id).to.equal(VideoChannelSyncState.WAITING_FIRST_RUN)
137 expect(new Date(videoChannelSync.createdAt)).to.be.above(startTestDate).and.to.be.at.most(new Date())
140 it('Should add a synchronization for another user', async function () {
141 const { videoChannelSync } = await servers[0].channelSyncs.create({
143 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
144 videoChannelId: userInfo.channelId
146 token: userInfo.accessToken
148 userInfo.syncId = videoChannelSync.id
151 it('Should not import a channel if not asked', async function () {
152 await waitJobs(servers)
154 const { data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
156 expect(data[0].state).to.contain({
157 id: VideoChannelSyncState.WAITING_FIRST_RUN,
158 label: 'Waiting first run'
162 it('Should only fetch the videos newer than the creation date', async function () {
163 this.timeout(120_000)
165 await changeDateForSync(userInfo.syncId, '2019-03-01')
167 await servers[0].debug.sendCommand({
169 command: 'process-video-channel-sync-latest'
173 await waitJobs(servers)
175 const { data, total } = await servers[0].videos.listByChannel({
176 handle: userInfo.channelName,
177 include: VideoInclude.NOT_PUBLISHED_STATE
180 expect(total).to.equal(1)
181 expect(data[0].name).to.equal('test')
184 it('Should list channel synchronizations', async function () {
187 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: 'root' })
188 expect(total).to.equal(2)
190 expect(data[0]).to.deep.contain({
191 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
193 id: VideoChannelSyncState.SYNCED,
194 label: 'Synchronized'
198 expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
200 expect(data[0].channel).to.contain({ id: servers[0].store.channel.id })
201 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
206 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
207 expect(total).to.equal(1)
208 expect(data[0]).to.deep.contain({
209 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
211 id: VideoChannelSyncState.SYNCED,
212 label: 'Synchronized'
218 it('Should list imports of a channel synchronization', async function () {
219 const { total, data } = await servers[0].imports.getMyVideoImports({ videoChannelSyncId: rootChannelSyncId })
221 expect(total).to.equal(1)
222 expect(data).to.have.lengthOf(1)
223 expect(data[0].video.name).to.equal('test')
226 it('Should remove user\'s channel synchronizations', async function () {
227 await servers[0].channelSyncs.delete({ channelSyncId: userInfo.syncId })
229 const { total } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
230 expect(total).to.equal(0)
233 // FIXME: youtube-dl doesn't work when speicifying a port after the hostname
234 // it('Should import a remote PeerTube channel', async function () {
235 // this.timeout(240_000)
237 // await servers[1].videos.quickUpload({ name: 'remote 1' })
238 // await waitJobs(servers)
240 // const { videoChannelSync } = await servers[0].channelSyncs.create({
242 // externalChannelUrl: servers[1].url + '/c/root_channel',
243 // videoChannelId: userInfo.channelId
245 // token: userInfo.accessToken
247 // await servers[0].channels.importVideos({
248 // channelName: userInfo.channelName,
249 // externalChannelUrl: servers[1].url + '/c/root_channel',
250 // videoChannelSyncId: videoChannelSync.id,
251 // token: userInfo.accessToken
254 // await waitJobs(servers)
256 // const { data, total } = await servers[0].videos.listByChannel({
257 // handle: userInfo.channelName,
258 // include: VideoInclude.NOT_PUBLISHED_STATE
261 // expect(total).to.equal(2)
262 // expect(data[0].name).to.equal('remote 1')
265 // it('Should keep synced a remote PeerTube channel', async function () {
266 // this.timeout(240_000)
268 // await servers[1].videos.quickUpload({ name: 'remote 2' })
269 // await waitJobs(servers)
271 // await servers[0].debug.sendCommand({
273 // command: 'process-video-channel-sync-latest'
277 // await waitJobs(servers)
279 // const { data, total } = await servers[0].videos.listByChannel({
280 // handle: userInfo.channelName,
281 // include: VideoInclude.NOT_PUBLISHED_STATE
283 // expect(total).to.equal(2)
284 // expect(data[0].name).to.equal('remote 2')
287 after(async function () {
288 await killallServers(servers)
293 runSuite('youtube-dl')