2 import { expect } from 'chai'
3 import { FIXTURE_URLS } from '@server/tests/shared'
4 import { areHttpImportTestsDisabled } from '@shared/core-utils'
5 import { HttpStatusCode, VideoChannelSyncState, VideoInclude, VideoPrivacy } from '@shared/models'
11 setAccessTokensToServers,
12 setDefaultAccountAvatar,
13 setDefaultChannelAvatar,
14 setDefaultVideoChannel,
16 } from '@shared/server-commands'
18 describe('Test channel synchronizations', function () {
19 if (areHttpImportTestsDisabled()) return
21 function runSuite (mode: 'youtube-dl' | 'yt-dlp') {
23 describe('Sync using ' + mode, function () {
24 let server: PeerTubeServer
25 let command: ChannelSyncsCommand
26 let startTestDate: Date
30 channelName: 'user1_channel',
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}`
43 before(async function () {
46 startTestDate = new Date()
48 server = await createSingleServer(1, getServerImportConfig(mode))
50 await setAccessTokensToServers([ server ])
51 await setDefaultVideoChannel([ server ])
52 await setDefaultChannelAvatar([ server ])
53 await setDefaultAccountAvatar([ server ])
55 await server.config.enableChannelSync()
57 command = server.channelSyncs
60 userInfo.accessToken = await server.users.generateUserAndToken(userInfo.username)
62 const { videoChannels } = await server.users.getMyInfo({ token: userInfo.accessToken })
63 userInfo.channelId = videoChannels[0].id
67 it('Should fetch the latest channel videos of a remote channel', async function () {
71 const { video } = await server.imports.importVideo({
73 channelId: server.store.channel.id,
74 privacy: VideoPrivacy.PUBLIC,
75 targetUrl: FIXTURE_URLS.youtube
79 expect(video.name).to.equal('small video - youtube')
81 const { total } = await server.videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
82 expect(total).to.equal(1)
85 const { videoChannelSync } = await command.create({
87 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
88 videoChannelId: server.store.channel.id
90 token: server.accessToken,
91 expectedStatus: HttpStatusCode.OK_200
94 // Ensure any missing video not already fetched will be considered as new
95 await changeDateForSync(videoChannelSync.id, '1970-01-01')
97 await server.debug.sendCommand({
99 command: 'process-video-channel-sync-latest'
104 await waitJobs(server)
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')
112 it('Should add another synchronization', async function () {
113 const externalChannelUrl = FIXTURE_URLS.youtubeChannel + '?foo=bar'
115 const { videoChannelSync } = await command.create({
118 videoChannelId: server.store.channel.id
120 token: server.accessToken,
121 expectedStatus: HttpStatusCode.OK_200
124 expect(videoChannelSync.externalChannelUrl).to.equal(externalChannelUrl)
125 expect(videoChannelSync.channel).to.include({
126 id: server.store.channel.id,
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())
133 it('Should add a synchronization for another user', async function () {
134 const { videoChannelSync } = await command.create({
136 externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?baz=qux',
137 videoChannelId: userInfo.channelId
139 token: userInfo.accessToken
141 userInfo.syncId = videoChannelSync.id
144 it('Should not import a channel if not asked', async function () {
145 await waitJobs(server)
147 const { data } = await command.listByAccount({ accountName: userInfo.username })
149 expect(data[0].state).to.contain({
150 id: VideoChannelSyncState.WAITING_FIRST_RUN,
151 label: 'Waiting first run'
155 it('Should only fetch the videos newer than the creation date', async function () {
156 this.timeout(120_000)
158 await changeDateForSync(userInfo.syncId, '2019-03-01')
160 await server.debug.sendCommand({
162 command: 'process-video-channel-sync-latest'
166 await waitJobs(server)
168 const { data, total } = await server.videos.listByChannel({
169 handle: userInfo.channelName,
170 include: VideoInclude.NOT_PUBLISHED_STATE
173 expect(total).to.equal(1)
174 expect(data[0].name).to.equal('test')
177 it('Should list channel synchronizations', async function () {
180 const { total, data } = await command.listByAccount({ accountName: 'root' })
181 expect(total).to.equal(2)
183 expect(data[0]).to.deep.contain({
184 externalChannelUrl: FIXTURE_URLS.youtubeChannel,
186 id: VideoChannelSyncState.SYNCED,
187 label: 'Synchronized'
191 expect(new Date(data[0].lastSyncAt)).to.be.greaterThan(startTestDate)
193 expect(data[0].channel).to.contain({ id: server.store.channel.id })
194 expect(data[1]).to.contain({ externalChannelUrl: FIXTURE_URLS.youtubeChannel + '?foo=bar' })
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',
204 id: VideoChannelSyncState.SYNCED,
205 label: 'Synchronized'
211 it('Should remove user\'s channel synchronizations', async function () {
212 await command.delete({ channelSyncId: userInfo.syncId })
214 const { total } = await command.listByAccount({ accountName: userInfo.username })
215 expect(total).to.equal(0)
218 after(async function () {
224 runSuite('youtube-dl')