1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import * as request from 'supertest'
6 import { Account, VideoPlaylistPrivacy } from '@shared/models'
18 setDefaultVideoChannel,
20 updateCustomSubConfig,
24 } from '../../shared/extra-utils'
25 import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
27 const expect = chai.expect
29 function checkIndexTags (html: string, title: string, description: string, css: string) {
30 expect(html).to.contain('<title>' + title + '</title>')
31 expect(html).to.contain('<meta name="description" content="' + description + '" />')
32 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>')
35 describe('Test a client controllers', function () {
36 let server: ServerInfo
39 const videoName = 'my super name for server 1'
40 const videoDescription = 'my super description for server 1'
42 const playlistName = 'super playlist name'
43 const playlistDescription = 'super playlist description'
44 let playlistUUID: string
46 const channelDescription = 'my super channel description'
48 before(async function () {
51 server = await flushAndRunServer(1)
52 server.accessToken = await serverLogin(server)
53 await setDefaultVideoChannel([ server ])
55 await updateVideoChannel(server.url, server.accessToken, server.videoChannel.name, { description: channelDescription })
59 const videoAttributes = { name: videoName, description: videoDescription }
60 await uploadVideo(server.url, server.accessToken, videoAttributes)
62 const resVideosRequest = await getVideosList(server.url)
63 const videos = resVideosRequest.body.data
64 expect(videos.length).to.equal(1)
66 server.video = videos[0]
70 const playlistAttrs = {
71 displayName: playlistName,
72 description: playlistDescription,
73 privacy: VideoPlaylistPrivacy.PUBLIC,
74 videoChannelId: server.videoChannel.id
77 const resVideoPlaylistRequest = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs })
79 const playlist = resVideoPlaylistRequest.body.videoPlaylist
80 const playlistId = playlist.id
81 playlistUUID = playlist.uuid
83 await addVideoInPlaylist({
85 token: server.accessToken,
87 elementAttrs: { videoId: server.video.id }
92 await updateMyUser({ url: server.url, accessToken: server.accessToken, description: 'my account description' })
94 const resAccountRequest = await getAccount(server.url, `${server.user.username}@${server.host}`)
95 account = resAccountRequest.body
98 describe('oEmbed', function () {
99 it('Should have valid oEmbed discovery tags for videos', async function () {
100 const path = '/videos/watch/' + server.video.uuid
101 const res = await request(server.url)
103 .set('Accept', 'text/html')
104 .expect(HttpStatusCode.OK_200)
106 const port = server.port
108 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
109 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2F${server.video.uuid}" ` +
110 `title="${server.video.name}" />`
112 expect(res.text).to.contain(expectedLink)
115 it('Should have valid oEmbed discovery tags for a playlist', async function () {
116 const res = await request(server.url)
117 .get('/videos/watch/playlist/' + playlistUUID)
118 .set('Accept', 'text/html')
119 .expect(HttpStatusCode.OK_200)
121 const port = server.port
123 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
124 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2Fplaylist%2F${playlistUUID}" ` +
125 `title="${playlistName}" />`
127 expect(res.text).to.contain(expectedLink)
131 describe('Open Graph', function () {
133 it('Should have valid Open Graph tags on the account page', async function () {
134 const res = await request(server.url)
135 .get('/accounts/' + server.user.username)
136 .set('Accept', 'text/html')
137 .expect(HttpStatusCode.OK_200)
139 expect(res.text).to.contain(`<meta property="og:title" content="${account.displayName}" />`)
140 expect(res.text).to.contain(`<meta property="og:description" content="${account.description}" />`)
141 expect(res.text).to.contain('<meta property="og:type" content="website" />')
142 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/accounts/${server.user.username}" />`)
145 it('Should have valid Open Graph tags on the channel page', async function () {
146 const res = await request(server.url)
147 .get('/video-channels/' + server.videoChannel.name)
148 .set('Accept', 'text/html')
149 .expect(HttpStatusCode.OK_200)
151 expect(res.text).to.contain(`<meta property="og:title" content="${server.videoChannel.displayName}" />`)
152 expect(res.text).to.contain(`<meta property="og:description" content="${channelDescription}" />`)
153 expect(res.text).to.contain('<meta property="og:type" content="website" />')
154 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/video-channels/${server.videoChannel.name}" />`)
157 it('Should have valid Open Graph tags on the watch page with video id', async function () {
158 const res = await request(server.url)
159 .get('/videos/watch/' + server.video.id)
160 .set('Accept', 'text/html')
161 .expect(HttpStatusCode.OK_200)
163 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
164 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`)
165 expect(res.text).to.contain('<meta property="og:type" content="video" />')
166 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/${server.video.uuid}" />`)
169 it('Should have valid Open Graph tags on the watch page with video uuid', async function () {
170 const res = await request(server.url)
171 .get('/videos/watch/' + server.video.uuid)
172 .set('Accept', 'text/html')
173 .expect(HttpStatusCode.OK_200)
175 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
176 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`)
177 expect(res.text).to.contain('<meta property="og:type" content="video" />')
178 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/${server.video.uuid}" />`)
181 it('Should have valid Open Graph tags on the watch playlist page', async function () {
182 const res = await request(server.url)
183 .get('/videos/watch/playlist/' + playlistUUID)
184 .set('Accept', 'text/html')
185 .expect(HttpStatusCode.OK_200)
187 expect(res.text).to.contain(`<meta property="og:title" content="${playlistName}" />`)
188 expect(res.text).to.contain(`<meta property="og:description" content="${playlistDescription}" />`)
189 expect(res.text).to.contain('<meta property="og:type" content="video" />')
190 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/playlist/${playlistUUID}" />`)
194 describe('Twitter card', async function () {
196 it('Should have valid twitter card on the watch video page', async function () {
197 const res = await request(server.url)
198 .get('/videos/watch/' + server.video.uuid)
199 .set('Accept', 'text/html')
200 .expect(HttpStatusCode.OK_200)
202 expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
203 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
204 expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`)
205 expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescription}" />`)
208 it('Should have valid twitter card on the watch playlist page', async function () {
209 const res = await request(server.url)
210 .get('/videos/watch/playlist/' + playlistUUID)
211 .set('Accept', 'text/html')
212 .expect(HttpStatusCode.OK_200)
214 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
215 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
216 expect(res.text).to.contain(`<meta property="twitter:title" content="${playlistName}" />`)
217 expect(res.text).to.contain(`<meta property="twitter:description" content="${playlistDescription}" />`)
220 it('Should have valid twitter card on the account page', async function () {
221 const res = await request(server.url)
222 .get('/accounts/' + account.name)
223 .set('Accept', 'text/html')
224 .expect(HttpStatusCode.OK_200)
226 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
227 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
228 expect(res.text).to.contain(`<meta property="twitter:title" content="${account.name}" />`)
229 expect(res.text).to.contain(`<meta property="twitter:description" content="${account.description}" />`)
232 it('Should have valid twitter card on the channel page', async function () {
233 const res = await request(server.url)
234 .get('/video-channels/' + server.videoChannel.name)
235 .set('Accept', 'text/html')
236 .expect(HttpStatusCode.OK_200)
238 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
239 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
240 expect(res.text).to.contain(`<meta property="twitter:title" content="${server.videoChannel.displayName}" />`)
241 expect(res.text).to.contain(`<meta property="twitter:description" content="${channelDescription}" />`)
244 it('Should have valid twitter card if Twitter is whitelisted', async function () {
245 const res1 = await getCustomConfig(server.url, server.accessToken)
246 const config = res1.body
247 config.services.twitter = {
251 await updateCustomConfig(server.url, server.accessToken, config)
253 const resVideoRequest = await request(server.url)
254 .get('/videos/watch/' + server.video.uuid)
255 .set('Accept', 'text/html')
256 .expect(HttpStatusCode.OK_200)
258 expect(resVideoRequest.text).to.contain('<meta property="twitter:card" content="player" />')
259 expect(resVideoRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
261 const resVideoPlaylistRequest = await request(server.url)
262 .get('/videos/watch/playlist/' + playlistUUID)
263 .set('Accept', 'text/html')
264 .expect(HttpStatusCode.OK_200)
266 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:card" content="player" />')
267 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
269 const resAccountRequest = await request(server.url)
270 .get('/accounts/' + account.name)
271 .set('Accept', 'text/html')
272 .expect(HttpStatusCode.OK_200)
274 expect(resAccountRequest.text).to.contain('<meta property="twitter:card" content="summary" />')
275 expect(resAccountRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
277 const resChannelRequest = await request(server.url)
278 .get('/video-channels/' + server.videoChannel.name)
279 .set('Accept', 'text/html')
280 .expect(HttpStatusCode.OK_200)
282 expect(resChannelRequest.text).to.contain('<meta property="twitter:card" content="summary" />')
283 expect(resChannelRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
287 describe('Index HTML', function () {
289 it('Should have valid index html tags (title, description...)', async function () {
290 const res = await makeHTMLRequest(server.url, '/videos/trending')
292 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
293 checkIndexTags(res.text, 'PeerTube', description, '')
296 it('Should update the customized configuration and have the correct index html tags', async function () {
297 await updateCustomSubConfig(server.url, server.accessToken, {
299 name: 'PeerTube updated',
300 shortDescription: 'my short description',
301 description: 'my super description',
302 terms: 'my super terms',
303 defaultClientRoute: '/videos/recently-added',
304 defaultNSFWPolicy: 'blur',
306 javascript: 'alert("coucou")',
307 css: 'body { background-color: red; }'
312 const res = await makeHTMLRequest(server.url, '/videos/trending')
314 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
317 it('Should have valid index html updated tags (title, description...)', async function () {
318 const res = await makeHTMLRequest(server.url, '/videos/trending')
320 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
324 after(async function () {
325 await cleanupTests([ server ])