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'
26 const expect = chai.expect
28 function checkIndexTags (html: string, title: string, description: string, css: string) {
29 expect(html).to.contain('<title>' + title + '</title>')
30 expect(html).to.contain('<meta name="description" content="' + description + '" />')
31 expect(html).to.contain('<style class="custom-css-style">' + css + '</style>')
34 describe('Test a client controllers', function () {
35 let server: ServerInfo
38 const videoName = 'my super name for server 1'
39 const videoDescription = 'my super description for server 1'
41 const playlistName = 'super playlist name'
42 const playlistDescription = 'super playlist description'
43 let playlistUUID: string
45 const channelDescription = 'my super channel description'
47 before(async function () {
50 server = await flushAndRunServer(1)
51 server.accessToken = await serverLogin(server)
52 await setDefaultVideoChannel([ server ])
54 await updateVideoChannel(server.url, server.accessToken, server.videoChannel.name, { description: channelDescription })
58 const videoAttributes = { name: videoName, description: videoDescription }
59 await uploadVideo(server.url, server.accessToken, videoAttributes)
61 const resVideosRequest = await getVideosList(server.url)
62 const videos = resVideosRequest.body.data
63 expect(videos.length).to.equal(1)
65 server.video = videos[0]
69 const playlistAttrs = {
70 displayName: playlistName,
71 description: playlistDescription,
72 privacy: VideoPlaylistPrivacy.PUBLIC,
73 videoChannelId: server.videoChannel.id
76 const resVideoPlaylistRequest = await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs })
78 const playlist = resVideoPlaylistRequest.body.videoPlaylist
79 const playlistId = playlist.id
80 playlistUUID = playlist.uuid
82 await addVideoInPlaylist({
84 token: server.accessToken,
86 elementAttrs: { videoId: server.video.id }
91 await updateMyUser({ url: server.url, accessToken: server.accessToken, description: 'my account description' })
93 const resAccountRequest = await getAccount(server.url, `${server.user.username}@${server.host}`)
94 account = resAccountRequest.body
97 describe('oEmbed', function () {
98 it('Should have valid oEmbed discovery tags for videos', async function () {
99 const path = '/videos/watch/' + server.video.uuid
100 const res = await request(server.url)
102 .set('Accept', 'text/html')
105 const port = server.port
107 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
108 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2F${server.video.uuid}" ` +
109 `title="${server.video.name}" />`
111 expect(res.text).to.contain(expectedLink)
114 it('Should have valid oEmbed discovery tags for a playlist', async function () {
115 const res = await request(server.url)
116 .get('/videos/watch/playlist/' + playlistUUID)
117 .set('Accept', 'text/html')
120 const port = server.port
122 const expectedLink = '<link rel="alternate" type="application/json+oembed" href="http://localhost:' + port + '/services/oembed?' +
123 `url=http%3A%2F%2Flocalhost%3A${port}%2Fvideos%2Fwatch%2Fplaylist%2F${playlistUUID}" ` +
124 `title="${playlistName}" />`
126 expect(res.text).to.contain(expectedLink)
130 describe('Open Graph', function () {
132 it('Should have valid Open Graph tags on the account page', async function () {
133 const res = await request(server.url)
134 .get('/accounts/' + server.user.username)
135 .set('Accept', 'text/html')
138 expect(res.text).to.contain(`<meta property="og:title" content="${account.displayName}" />`)
139 expect(res.text).to.contain(`<meta property="og:description" content="${account.description}" />`)
140 expect(res.text).to.contain('<meta property="og:type" content="website" />')
141 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/accounts/${server.user.username}" />`)
144 it('Should have valid Open Graph tags on the channel page', async function () {
145 const res = await request(server.url)
146 .get('/video-channels/' + server.videoChannel.name)
147 .set('Accept', 'text/html')
150 expect(res.text).to.contain(`<meta property="og:title" content="${server.videoChannel.displayName}" />`)
151 expect(res.text).to.contain(`<meta property="og:description" content="${channelDescription}" />`)
152 expect(res.text).to.contain('<meta property="og:type" content="website" />')
153 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/video-channels/${server.videoChannel.name}" />`)
156 it('Should have valid Open Graph tags on the watch page with video id', async function () {
157 const res = await request(server.url)
158 .get('/videos/watch/' + server.video.id)
159 .set('Accept', 'text/html')
162 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
163 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`)
164 expect(res.text).to.contain('<meta property="og:type" content="video" />')
165 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/${server.video.uuid}" />`)
168 it('Should have valid Open Graph tags on the watch page with video uuid', async function () {
169 const res = await request(server.url)
170 .get('/videos/watch/' + server.video.uuid)
171 .set('Accept', 'text/html')
174 expect(res.text).to.contain(`<meta property="og:title" content="${videoName}" />`)
175 expect(res.text).to.contain(`<meta property="og:description" content="${videoDescription}" />`)
176 expect(res.text).to.contain('<meta property="og:type" content="video" />')
177 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/${server.video.uuid}" />`)
180 it('Should have valid Open Graph tags on the watch playlist page', async function () {
181 const res = await request(server.url)
182 .get('/videos/watch/playlist/' + playlistUUID)
183 .set('Accept', 'text/html')
186 expect(res.text).to.contain(`<meta property="og:title" content="${playlistName}" />`)
187 expect(res.text).to.contain(`<meta property="og:description" content="${playlistDescription}" />`)
188 expect(res.text).to.contain('<meta property="og:type" content="video" />')
189 expect(res.text).to.contain(`<meta property="og:url" content="${server.url}/videos/watch/playlist/${playlistUUID}" />`)
193 describe('Twitter card', async function () {
195 it('Should have valid twitter card on the watch video page', async function () {
196 const res = await request(server.url)
197 .get('/videos/watch/' + server.video.uuid)
198 .set('Accept', 'text/html')
201 expect(res.text).to.contain('<meta property="twitter:card" content="summary_large_image" />')
202 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
203 expect(res.text).to.contain(`<meta property="twitter:title" content="${videoName}" />`)
204 expect(res.text).to.contain(`<meta property="twitter:description" content="${videoDescription}" />`)
207 it('Should have valid twitter card on the watch playlist page', async function () {
208 const res = await request(server.url)
209 .get('/videos/watch/playlist/' + playlistUUID)
210 .set('Accept', 'text/html')
213 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
214 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
215 expect(res.text).to.contain(`<meta property="twitter:title" content="${playlistName}" />`)
216 expect(res.text).to.contain(`<meta property="twitter:description" content="${playlistDescription}" />`)
219 it('Should have valid twitter card on the account page', async function () {
220 const res = await request(server.url)
221 .get('/accounts/' + account.name)
222 .set('Accept', 'text/html')
225 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
226 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
227 expect(res.text).to.contain(`<meta property="twitter:title" content="${account.name}" />`)
228 expect(res.text).to.contain(`<meta property="twitter:description" content="${account.description}" />`)
231 it('Should have valid twitter card on the channel page', async function () {
232 const res = await request(server.url)
233 .get('/video-channels/' + server.videoChannel.name)
234 .set('Accept', 'text/html')
237 expect(res.text).to.contain('<meta property="twitter:card" content="summary" />')
238 expect(res.text).to.contain('<meta property="twitter:site" content="@Chocobozzz" />')
239 expect(res.text).to.contain(`<meta property="twitter:title" content="${server.videoChannel.displayName}" />`)
240 expect(res.text).to.contain(`<meta property="twitter:description" content="${channelDescription}" />`)
243 it('Should have valid twitter card if Twitter is whitelisted', async function () {
244 const res1 = await getCustomConfig(server.url, server.accessToken)
245 const config = res1.body
246 config.services.twitter = {
250 await updateCustomConfig(server.url, server.accessToken, config)
252 const resVideoRequest = await request(server.url)
253 .get('/videos/watch/' + server.video.uuid)
254 .set('Accept', 'text/html')
257 expect(resVideoRequest.text).to.contain('<meta property="twitter:card" content="player" />')
258 expect(resVideoRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
260 const resVideoPlaylistRequest = await request(server.url)
261 .get('/videos/watch/playlist/' + playlistUUID)
262 .set('Accept', 'text/html')
265 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:card" content="player" />')
266 expect(resVideoPlaylistRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
268 const resAccountRequest = await request(server.url)
269 .get('/accounts/' + account.name)
270 .set('Accept', 'text/html')
273 expect(resAccountRequest.text).to.contain('<meta property="twitter:card" content="summary" />')
274 expect(resAccountRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
276 const resChannelRequest = await request(server.url)
277 .get('/video-channels/' + server.videoChannel.name)
278 .set('Accept', 'text/html')
281 expect(resChannelRequest.text).to.contain('<meta property="twitter:card" content="summary" />')
282 expect(resChannelRequest.text).to.contain('<meta property="twitter:site" content="@Kuja" />')
286 describe('Index HTML', function () {
288 it('Should have valid index html tags (title, description...)', async function () {
289 const res = await makeHTMLRequest(server.url, '/videos/trending')
291 const description = 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
292 checkIndexTags(res.text, 'PeerTube', description, '')
295 it('Should update the customized configuration and have the correct index html tags', async function () {
296 await updateCustomSubConfig(server.url, server.accessToken, {
298 name: 'PeerTube updated',
299 shortDescription: 'my short description',
300 description: 'my super description',
301 terms: 'my super terms',
302 defaultClientRoute: '/videos/recently-added',
303 defaultNSFWPolicy: 'blur',
305 javascript: 'alert("coucou")',
306 css: 'body { background-color: red; }'
311 const res = await makeHTMLRequest(server.url, '/videos/trending')
313 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
316 it('Should have valid index html updated tags (title, description...)', async function () {
317 const res = await makeHTMLRequest(server.url, '/videos/trending')
319 checkIndexTags(res.text, 'PeerTube updated', 'my short description', 'body { background-color: red; }')
323 after(async function () {
324 await cleanupTests([ server ])