diff options
Diffstat (limited to 'server/tests/api/videos/video-channel-syncs.ts')
-rw-r--r-- | server/tests/api/videos/video-channel-syncs.ts | 226 |
1 files changed, 226 insertions, 0 deletions
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 @@ | |||
1 | import 'mocha' | ||
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' | ||
6 | import { | ||
7 | ChannelSyncsCommand, | ||
8 | createSingleServer, | ||
9 | getServerImportConfig, | ||
10 | PeerTubeServer, | ||
11 | setAccessTokensToServers, | ||
12 | setDefaultAccountAvatar, | ||
13 | setDefaultChannelAvatar, | ||
14 | setDefaultVideoChannel, | ||
15 | waitJobs | ||
16 | } from '@shared/server-commands' | ||
17 | |||
18 | describe('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 | }) | ||