1 import { expect } from 'chai'
2 import { FIXTURE_URLS } from '@server/tests/shared'
3 import { areHttpImportTestsDisabled } from '@shared/core-utils'
4 import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
10 setAccessTokensToServers,
11 setDefaultAccountAvatar,
12 setDefaultChannelAvatar,
13 setDefaultVideoChannel,
15 } from '@shared/server-commands'
17 describe('Test channel synchronizations', function () {
18 if (areHttpImportTestsDisabled()) return
20 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
22 describe('Sync using ' + mode, function () {
23 let servers: PeerTubeServer[]
25 let startTestDate: Date
27 let rootChannelSyncId: number
31 channelName: 'user1_channel',
36 async function changeDateForSync (channelSyncId: number, newDate: string) {
37 await servers[0].sql.updateQuery(
38 `UPDATE "videoChannelSync" ` +
39 `SET "createdAt"='${newDate}', "lastSyncAt"='${newDate}' ` +
40 `WHERE id=${channelSyncId}`
44 before(async function () {
47 startTestDate = new Date()
49 servers = await createMultipleServers(2, getServerImportConfig(mode))
51 await setAccessTokensToServers(servers)
52 await setDefaultVideoChannel(servers)
53 await setDefaultChannelAvatar(servers)
54 await setDefaultAccountAvatar(servers)
56 await servers[0].config.enableChannelSync()
59 userInfo.accessToken = await servers[0].users.generateUserAndToken(userInfo.username)
61 const { videoChannels } = await servers[0].users.getMyInfo({ token: userInfo.accessToken })
62 userInfo.channelId = videoChannels[0].id
66 it('Should fetch the latest channel videos of a remote channel', async function () {
70 const { video } = await servers[0].imports.importVideo({
72 channelId: servers[0].store.channel.id,
73 privacy: VideoPrivacy.PUBLIC,
74 targetUrl: FIXTURE_URLS.youtube
78 expect(video.name).to.equal('small video - youtube')
80 const { total } = await servers[0].videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
81 expect(total).to.equal(1)
84 const { videoChannelSync } = await servers[0].channelSyncs.create({
86 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
87 videoChannelId: servers[0].store.channel.id
89 token: servers[0].accessToken,
90 expectedStatus: HttpStatusCode.OK_200
92 rootChannelSyncId = videoChannelSync.id
94 // Ensure any missing video not already fetched will be considered as new
95 await changeDateForSync(videoChannelSync.id, '1970-01-01')
97 await servers[0].debug.sendCommand({
99 command: 'process-video-channel-sync-latest'
104 await waitJobs(servers)
106 const { total, data } = await servers[0].videos.listByChannel({
107 handle: 'root_channel',
108 include: VideoInclude.NOT_PUBLISHED_STATE
110 expect(total).to.equal(2)
111 expect(data[0].name).to.equal('test')
115 it('Should add another synchronization', async function () {
116 const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
118 const { videoChannelSync } = await servers[0].channelSyncs.create({
121 videoChannelId: servers[0].store.channel.id
123 token: servers[0].accessToken,
124 expectedStatus: HttpStatusCode.OK_200
127 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
128 expect(videoChannelSync.channel).to.include({
129 id: servers[0].store.channel.id,
132 expect(videoChannelSync.state.id).to.equal(VideoChannelSyncState.WAITING_FIRST_RUN)
133 expect(new Date(videoChannelSync.createdAt)).to.be.above(startTestDate).and.to.be.at.most(new Date())
136 it('Should add a synchronization for another user', async function () {
137 const { videoChannelSync } = await servers[0].channelSyncs.create({
139 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
140 videoChannelId: userInfo.channelId
142 token: userInfo.accessToken
144 userInfo.syncId = videoChannelSync.id
147 it('Should not import a channel if not asked', async function () {
148 await waitJobs(servers)
150 const { data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
152 expect(data[0].state).to.contain({
153 id: VideoChannelSyncState.WAITING_FIRST_RUN,
154 label: 'Waiting first run'
158 it('Should only fetch the videos newer than the creation date', async function () {
159 this.timeout(120_000)
161 await changeDateForSync(userInfo.syncId, '2019-03-01')
163 await servers[0].debug.sendCommand({
165 command: 'process-video-channel-sync-latest'
169 await waitJobs(servers)
171 const { data, total } = await servers[0].videos.listByChannel({
172 handle: userInfo.channelName,
173 include: VideoInclude.NOT_PUBLISHED_STATE
176 expect(total).to.equal(1)
177 expect(data[0].name).to.equal('test')
180 it('Should list channel synchronizations', async function () {
183 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: 'root' })
184 expect(total).to.equal(2)
186 expect(data[0]).to.deep.contain({
187 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
189 id: VideoChannelSyncState.SYNCED,
190 label: 'Synchronized'
194 expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
196 expect(data[0].channel).to.contain({ id: servers[0].store.channel.id })
197 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
202 const { total, data } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
203 expect(total).to.equal(1)
204 expect(data[0]).to.deep.contain({
205 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
207 id: VideoChannelSyncState.SYNCED,
208 label: 'Synchronized'
214 it('Should list imports of a channel synchronization', async function () {
215 const { total, data } = await servers[0].imports.getMyVideoImports({ videoChannelSyncId: rootChannelSyncId })
217 expect(total).to.equal(1)
218 expect(data).to.have.lengthOf(1)
219 expect(data[0].video.name).to.equal('test')
222 it('Should remove user\'s channel synchronizations', async function () {
223 await servers[0].channelSyncs.delete({ channelSyncId: userInfo.syncId })
225 const { total } = await servers[0].channelSyncs.listByAccount({ accountName: userInfo.username })
226 expect(total).to.equal(0)
229 // FIXME: youtube-dl doesn't work when speicifying a port after the hostname
230 // it('Should import a remote PeerTube channel', async function () {
231 // this.timeout(240_000)
233 // await servers[1].videos.quickUpload({ name: 'remote 1' })
234 // await waitJobs(servers)
236 // const { videoChannelSync } = await servers[0].channelSyncs.create({
238 // externalChannelUrl: servers[1].url + '/c/root_channel',
239 // videoChannelId: userInfo.channelId
241 // token: userInfo.accessToken
243 // await servers[0].channels.importVideos({
244 // channelName: userInfo.channelName,
245 // externalChannelUrl: servers[1].url + '/c/root_channel',
246 // videoChannelSyncId: videoChannelSync.id,
247 // token: userInfo.accessToken
250 // await waitJobs(servers)
252 // const { data, total } = await servers[0].videos.listByChannel({
253 // handle: userInfo.channelName,
254 // include: VideoInclude.NOT_PUBLISHED_STATE
257 // expect(total).to.equal(2)
258 // expect(data[0].name).to.equal('remote 1')
261 // it('Should keep synced a remote PeerTube channel', async function () {
262 // this.timeout(240_000)
264 // await servers[1].videos.quickUpload({ name: 'remote 2' })
265 // await waitJobs(servers)
267 // await servers[0].debug.sendCommand({
269 // command: 'process-video-channel-sync-latest'
273 // await waitJobs(servers)
275 // const { data, total } = await servers[0].videos.listByChannel({
276 // handle: userInfo.channelName,
277 // include: VideoInclude.NOT_PUBLISHED_STATE
279 // expect(total).to.equal(2)
280 // expect(data[0].name).to.equal('remote 2')
283 after(async function () {
284 await killallServers(servers)
289 runSuite('youtube-dl')