452d050125e153a3c87d14e0d0b829691c4dc10e
[oweals/peertube.git] / server / tests / api / server / plugins.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import {
6   cleanupTests,
7   closeAllSequelize,
8   flushAndRunServer,
9   getConfig,
10   getMyUserInformation,
11   getPlugin,
12   getPluginPackageJSON,
13   getPluginRegisteredSettings,
14   getPluginsCSS,
15   getPublicSettings,
16   installPlugin,
17   killallServers,
18   listAvailablePlugins,
19   listPlugins,
20   reRunServer,
21   ServerInfo,
22   setAccessTokensToServers,
23   setPluginVersion,
24   uninstallPlugin,
25   updateCustomSubConfig,
26   updateMyUser,
27   updatePlugin,
28   updatePluginPackageJSON,
29   updatePluginSettings,
30   wait
31 } from '../../../../shared/extra-utils'
32 import { PluginType } from '../../../../shared/models/plugins/plugin.type'
33 import { PeerTubePluginIndex } from '../../../../shared/models/plugins/peertube-plugin-index.model'
34 import { ServerConfig } from '../../../../shared/models/server'
35 import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugin.model'
36 import { User } from '../../../../shared/models/users'
37 import { PluginPackageJson } from '../../../../shared/models/plugins/plugin-package-json.model'
38 import { RegisteredServerSettings } from '../../../../shared/models/plugins/register-server-setting.model'
39 import { PublicServerSetting } from '../../../../shared/models/plugins/public-server.setting'
40
41 const expect = chai.expect
42
43 describe('Test plugins', function () {
44   let server: ServerInfo = null
45
46   before(async function () {
47     this.timeout(30000)
48
49     const configOverride = {
50       plugins: {
51         index: { check_latest_versions_interval: '5 seconds' }
52       }
53     }
54     server = await flushAndRunServer(1, configOverride)
55     await setAccessTokensToServers([ server ])
56   })
57
58   it('Should list and search available plugins and themes', async function () {
59     this.timeout(30000)
60
61     {
62       const res = await listAvailablePlugins({
63         url: server.url,
64         accessToken: server.accessToken,
65         count: 1,
66         start: 0,
67         pluginType: PluginType.THEME,
68         search: 'background-red'
69       })
70
71       expect(res.body.total).to.be.at.least(1)
72       expect(res.body.data).to.have.lengthOf(1)
73     }
74
75     {
76       const res1 = await listAvailablePlugins({
77         url: server.url,
78         accessToken: server.accessToken,
79         count: 2,
80         start: 0,
81         sort: 'npmName'
82       })
83       const data1: PeerTubePluginIndex[] = res1.body.data
84
85       expect(res1.body.total).to.be.at.least(2)
86       expect(data1).to.have.lengthOf(2)
87
88       const res2 = await listAvailablePlugins({
89         url: server.url,
90         accessToken: server.accessToken,
91         count: 2,
92         start: 0,
93         sort: '-npmName'
94       })
95       const data2: PeerTubePluginIndex[] = res2.body.data
96
97       expect(res2.body.total).to.be.at.least(2)
98       expect(data2).to.have.lengthOf(2)
99
100       expect(data1[0].npmName).to.not.equal(data2[0].npmName)
101     }
102
103     {
104       const res = await listAvailablePlugins({
105         url: server.url,
106         accessToken: server.accessToken,
107         count: 10,
108         start: 0,
109         pluginType: PluginType.THEME,
110         search: 'background-red',
111         currentPeerTubeEngine: '1.0.0'
112       })
113       const data: PeerTubePluginIndex[] = res.body.data
114
115       const p = data.find(p => p.npmName === 'peertube-theme-background-red')
116       expect(p).to.be.undefined
117     }
118   })
119
120   it('Should have an empty global css', async function () {
121     const res = await getPluginsCSS(server.url)
122
123     expect(res.text).to.be.empty
124   })
125
126   it('Should install a plugin and a theme', async function () {
127     this.timeout(30000)
128
129     await installPlugin({
130       url: server.url,
131       accessToken: server.accessToken,
132       npmName: 'peertube-plugin-hello-world'
133     })
134
135     await installPlugin({
136       url: server.url,
137       accessToken: server.accessToken,
138       npmName: 'peertube-theme-background-red'
139     })
140   })
141
142   it('Should have the correct global css', async function () {
143     const res = await getPluginsCSS(server.url)
144
145     expect(res.text).to.contain('--mainBackgroundColor')
146   })
147
148   it('Should have the plugin loaded in the configuration', async function () {
149     const res = await getConfig(server.url)
150     const config: ServerConfig = res.body
151
152     const theme = config.theme.registered.find(r => r.name === 'background-red')
153     expect(theme).to.not.be.undefined
154
155     const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
156     expect(plugin).to.not.be.undefined
157   })
158
159   it('Should update the default theme in the configuration', async function () {
160     await updateCustomSubConfig(server.url, server.accessToken, { theme: { default: 'background-red' } })
161
162     const res = await getConfig(server.url)
163     const config: ServerConfig = res.body
164
165     expect(config.theme.default).to.equal('background-red')
166   })
167
168   it('Should update my default theme', async function () {
169     await updateMyUser({
170       url: server.url,
171       accessToken: server.accessToken,
172       theme: 'background-red'
173     })
174
175     const res = await getMyUserInformation(server.url, server.accessToken)
176     expect((res.body as User).theme).to.equal('background-red')
177   })
178
179   it('Should list plugins and themes', async function () {
180     {
181       const res = await listPlugins({
182         url: server.url,
183         accessToken: server.accessToken,
184         count: 1,
185         start: 0,
186         pluginType: PluginType.THEME
187       })
188       const data: PeerTubePlugin[] = res.body.data
189
190       expect(res.body.total).to.be.at.least(1)
191       expect(data).to.have.lengthOf(1)
192       expect(data[0].name).to.equal('background-red')
193     }
194
195     {
196       const res = await listPlugins({
197         url: server.url,
198         accessToken: server.accessToken,
199         count: 2,
200         start: 0,
201         sort: 'name'
202       })
203       const data: PeerTubePlugin[] = res.body.data
204
205       expect(data[0].name).to.equal('background-red')
206       expect(data[1].name).to.equal('hello-world')
207     }
208
209     {
210       const res = await listPlugins({
211         url: server.url,
212         accessToken: server.accessToken,
213         count: 2,
214         start: 1,
215         sort: 'name'
216       })
217       const data: PeerTubePlugin[] = res.body.data
218
219       expect(data[0].name).to.equal('hello-world')
220     }
221   })
222
223   it('Should get registered settings', async function () {
224     const res = await getPluginRegisteredSettings({
225       url: server.url,
226       accessToken: server.accessToken,
227       npmName: 'peertube-plugin-hello-world'
228     })
229
230     const registeredSettings = (res.body as RegisteredServerSettings).registeredSettings
231
232     expect(registeredSettings).to.have.length.at.least(1)
233
234     const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name')
235     expect(adminNameSettings).to.not.be.undefined
236   })
237
238   it('Should get public settings', async function () {
239     const res = await getPublicSettings({ url: server.url, npmName: 'peertube-plugin-hello-world' })
240
241     const publicSettings = (res.body as PublicServerSetting).publicSettings
242
243     expect(Object.keys(publicSettings)).to.have.lengthOf(1)
244     expect(Object.keys(publicSettings)).to.deep.equal([ 'user-name' ])
245     expect(publicSettings['user-name']).to.be.null
246   })
247
248   it('Should update the settings', async function () {
249     const settings = {
250       'admin-name': 'Cid'
251     }
252
253     await updatePluginSettings({
254       url: server.url,
255       accessToken: server.accessToken,
256       npmName: 'peertube-plugin-hello-world',
257       settings
258     })
259   })
260
261   it('Should get a plugin and a theme', async function () {
262     {
263       const res = await getPlugin({
264         url: server.url,
265         accessToken: server.accessToken,
266         npmName: 'peertube-plugin-hello-world'
267       })
268
269       const plugin: PeerTubePlugin = res.body
270
271       expect(plugin.type).to.equal(PluginType.PLUGIN)
272       expect(plugin.name).to.equal('hello-world')
273       expect(plugin.description).to.exist
274       expect(plugin.homepage).to.exist
275       expect(plugin.uninstalled).to.be.false
276       expect(plugin.enabled).to.be.true
277       expect(plugin.description).to.exist
278       expect(plugin.version).to.exist
279       expect(plugin.peertubeEngine).to.exist
280       expect(plugin.createdAt).to.exist
281
282       expect(plugin.settings).to.not.be.undefined
283       expect(plugin.settings['admin-name']).to.equal('Cid')
284     }
285
286     {
287       const res = await getPlugin({
288         url: server.url,
289         accessToken: server.accessToken,
290         npmName: 'peertube-theme-background-red'
291       })
292
293       const plugin: PeerTubePlugin = res.body
294
295       expect(plugin.type).to.equal(PluginType.THEME)
296       expect(plugin.name).to.equal('background-red')
297       expect(plugin.description).to.exist
298       expect(plugin.homepage).to.exist
299       expect(plugin.uninstalled).to.be.false
300       expect(plugin.enabled).to.be.true
301       expect(plugin.description).to.exist
302       expect(plugin.version).to.exist
303       expect(plugin.peertubeEngine).to.exist
304       expect(plugin.createdAt).to.exist
305
306       expect(plugin.settings).to.be.null
307     }
308   })
309
310   it('Should update the plugin and the theme', async function () {
311     this.timeout(30000)
312
313     // Wait the scheduler that get the latest plugins versions
314     await wait(6000)
315
316     // Fake update our plugin version
317     await setPluginVersion(server.internalServerNumber, 'hello-world', '0.0.1')
318
319     // Fake update package.json
320     const packageJSON: PluginPackageJson = await getPluginPackageJSON(server, 'peertube-plugin-hello-world')
321     const oldVersion = packageJSON.version
322
323     packageJSON.version = '0.0.1'
324     await updatePluginPackageJSON(server, 'peertube-plugin-hello-world', packageJSON)
325
326     // Restart the server to take into account this change
327     killallServers([ server ])
328     await reRunServer(server)
329
330     {
331       const res = await listPlugins({
332         url: server.url,
333         accessToken: server.accessToken,
334         pluginType: PluginType.PLUGIN
335       })
336
337       const plugin: PeerTubePlugin = res.body.data[0]
338
339       expect(plugin.version).to.equal('0.0.1')
340       expect(plugin.latestVersion).to.exist
341       expect(plugin.latestVersion).to.not.equal('0.0.1')
342     }
343
344     {
345       await updatePlugin({
346         url: server.url,
347         accessToken: server.accessToken,
348         npmName: 'peertube-plugin-hello-world'
349       })
350
351       const res = await listPlugins({
352         url: server.url,
353         accessToken: server.accessToken,
354         pluginType: PluginType.PLUGIN
355       })
356
357       const plugin: PeerTubePlugin = res.body.data[0]
358
359       expect(plugin.version).to.equal(oldVersion)
360
361       const updatedPackageJSON: PluginPackageJson = await getPluginPackageJSON(server, 'peertube-plugin-hello-world')
362       expect(updatedPackageJSON.version).to.equal(oldVersion)
363     }
364   })
365
366   it('Should uninstall the plugin', async function () {
367     await uninstallPlugin({
368       url: server.url,
369       accessToken: server.accessToken,
370       npmName: 'peertube-plugin-hello-world'
371     })
372
373     const res = await listPlugins({
374       url: server.url,
375       accessToken: server.accessToken,
376       pluginType: PluginType.PLUGIN
377     })
378
379     expect(res.body.total).to.equal(0)
380     expect(res.body.data).to.have.lengthOf(0)
381   })
382
383   it('Should have an empty global css', async function () {
384     const res = await getPluginsCSS(server.url)
385
386     expect(res.text).to.be.empty
387   })
388
389   it('Should list uninstalled plugins', async function () {
390     const res = await listPlugins({
391       url: server.url,
392       accessToken: server.accessToken,
393       pluginType: PluginType.PLUGIN,
394       uninstalled: true
395     })
396
397     expect(res.body.total).to.equal(1)
398     expect(res.body.data).to.have.lengthOf(1)
399
400     const plugin: PeerTubePlugin = res.body.data[0]
401     expect(plugin.name).to.equal('hello-world')
402     expect(plugin.enabled).to.be.false
403     expect(plugin.uninstalled).to.be.true
404   })
405
406   it('Should uninstall the theme', async function () {
407     await uninstallPlugin({
408       url: server.url,
409       accessToken: server.accessToken,
410       npmName: 'peertube-theme-background-red'
411     })
412   })
413
414   it('Should have updated the configuration', async function () {
415     // get /config (default theme + registered themes + registered plugins)
416     const res = await getConfig(server.url)
417     const config: ServerConfig = res.body
418
419     expect(config.theme.default).to.equal('default')
420
421     const theme = config.theme.registered.find(r => r.name === 'background-red')
422     expect(theme).to.be.undefined
423
424     const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
425     expect(plugin).to.be.undefined
426   })
427
428   it('Should have updated the user theme', async function () {
429     const res = await getMyUserInformation(server.url, server.accessToken)
430     expect((res.body as User).theme).to.equal('instance-default')
431   })
432
433   after(async function () {
434     await closeAllSequelize([ server ])
435     await cleanupTests([ server ])
436   })
437 })