]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/server/plugins.ts
We don't need to import mocha
[github/Chocobozzz/PeerTube.git] / server / tests / api / server / plugins.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
9b474844 2
9b474844 3import * as chai from 'chai'
c795e196
C
4import { pathExists, remove } from 'fs-extra'
5import { join } from 'path'
c55e3d72
C
6import { testHelloWorldRegisteredSettings } from '@server/tests/shared'
7import { wait } from '@shared/core-utils'
8import { HttpStatusCode, PluginType } from '@shared/models'
9b474844
C
9import {
10 cleanupTests,
254d3579 11 createSingleServer,
a1587156 12 killallServers,
c795e196 13 makeGetRequest,
254d3579 14 PeerTubeServer,
4c7e60bc 15 PluginsCommand,
c55e3d72 16 setAccessTokensToServers
bf54587a 17} from '@shared/server-commands'
9b474844
C
18
19const expect = chai.expect
20
21describe('Test plugins', function () {
254d3579 22 let server: PeerTubeServer = null
ae2abfd3 23 let command: PluginsCommand
9b474844
C
24
25 before(async function () {
26 this.timeout(30000)
27
09071200
C
28 const configOverride = {
29 plugins: {
30 index: { check_latest_versions_interval: '5 seconds' }
31 }
32 }
254d3579 33 server = await createSingleServer(1, configOverride)
9b474844 34 await setAccessTokensToServers([ server ])
a5461888 35
89d241a7 36 command = server.plugins
09071200
C
37 })
38
39 it('Should list and search available plugins and themes', async function () {
40 this.timeout(30000)
9b474844
C
41
42 {
ae2abfd3 43 const body = await command.listAvailable({
09071200
C
44 count: 1,
45 start: 0,
46 pluginType: PluginType.THEME,
47 search: 'background-red'
48 })
49
ae2abfd3
C
50 expect(body.total).to.be.at.least(1)
51 expect(body.data).to.have.lengthOf(1)
9b474844
C
52 }
53
54 {
ae2abfd3 55 const body1 = await command.listAvailable({
09071200
C
56 count: 2,
57 start: 0,
58 sort: 'npmName'
59 })
ae2abfd3 60 expect(body1.total).to.be.at.least(2)
09071200 61
ae2abfd3 62 const data1 = body1.data
09071200
C
63 expect(data1).to.have.lengthOf(2)
64
ae2abfd3 65 const body2 = await command.listAvailable({
09071200
C
66 count: 2,
67 start: 0,
68 sort: '-npmName'
69 })
ae2abfd3 70 expect(body2.total).to.be.at.least(2)
09071200 71
ae2abfd3 72 const data2 = body2.data
09071200
C
73 expect(data2).to.have.lengthOf(2)
74
a1587156 75 expect(data1[0].npmName).to.not.equal(data2[0].npmName)
9b474844 76 }
9b474844 77
09071200 78 {
ae2abfd3 79 const body = await command.listAvailable({
09071200
C
80 count: 10,
81 start: 0,
82 pluginType: PluginType.THEME,
83 search: 'background-red',
84 currentPeerTubeEngine: '1.0.0'
85 })
9b474844 86
ae2abfd3 87 const p = body.data.find(p => p.npmName === 'peertube-theme-background-red')
09071200
C
88 expect(p).to.be.undefined
89 }
9b474844
C
90 })
91
9b474844 92 it('Should install a plugin and a theme', async function () {
09071200
C
93 this.timeout(30000)
94
ae2abfd3
C
95 await command.install({ npmName: 'peertube-plugin-hello-world' })
96 await command.install({ npmName: 'peertube-theme-background-red' })
9b474844
C
97 })
98
9b474844 99 it('Should have the plugin loaded in the configuration', async function () {
2769876f
C
100 for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
101 const theme = config.theme.registered.find(r => r.name === 'background-red')
102 expect(theme).to.not.be.undefined
103 expect(theme.npmName).to.equal('peertube-theme-background-red')
104
105 const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
106 expect(plugin).to.not.be.undefined
107 expect(plugin.npmName).to.equal('peertube-plugin-hello-world')
108 }
9b474844
C
109 })
110
111 it('Should update the default theme in the configuration', async function () {
89d241a7 112 await server.config.updateCustomSubConfig({
65e6e260
C
113 newConfig: {
114 theme: { default: 'background-red' }
115 }
116 })
09071200 117
2769876f
C
118 for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
119 expect(config.theme.default).to.equal('background-red')
120 }
9b474844
C
121 })
122
09071200 123 it('Should update my default theme', async function () {
89d241a7 124 await server.users.updateMe({ theme: 'background-red' })
09071200 125
89d241a7 126 const user = await server.users.getMyInfo()
7926c5f9 127 expect(user.theme).to.equal('background-red')
9b474844
C
128 })
129
09071200
C
130 it('Should list plugins and themes', async function () {
131 {
ae2abfd3 132 const body = await command.list({
09071200
C
133 count: 1,
134 start: 0,
135 pluginType: PluginType.THEME
136 })
ae2abfd3 137 expect(body.total).to.be.at.least(1)
09071200 138
ae2abfd3 139 const data = body.data
09071200
C
140 expect(data).to.have.lengthOf(1)
141 expect(data[0].name).to.equal('background-red')
142 }
143
144 {
dd0ebb71 145 const { data } = await command.list({
09071200
C
146 count: 2,
147 start: 0,
148 sort: 'name'
149 })
09071200
C
150
151 expect(data[0].name).to.equal('background-red')
152 expect(data[1].name).to.equal('hello-world')
153 }
154
155 {
ae2abfd3 156 const body = await command.list({
09071200
C
157 count: 2,
158 start: 1,
159 sort: 'name'
160 })
09071200 161
ae2abfd3 162 expect(body.data[0].name).to.equal('hello-world')
09071200 163 }
9b474844
C
164 })
165
166 it('Should get registered settings', async function () {
353f8bc0 167 await testHelloWorldRegisteredSettings(server)
9b474844
C
168 })
169
ba211e73 170 it('Should get public settings', async function () {
ae2abfd3
C
171 const body = await command.getPublicSettings({ npmName: 'peertube-plugin-hello-world' })
172 const publicSettings = body.publicSettings
ba211e73
C
173
174 expect(Object.keys(publicSettings)).to.have.lengthOf(1)
175 expect(Object.keys(publicSettings)).to.deep.equal([ 'user-name' ])
176 expect(publicSettings['user-name']).to.be.null
177 })
178
9b474844 179 it('Should update the settings', async function () {
09071200
C
180 const settings = {
181 'admin-name': 'Cid'
182 }
183
ae2abfd3 184 await command.updateSettings({
09071200
C
185 npmName: 'peertube-plugin-hello-world',
186 settings
187 })
188 })
189
a5896799
C
190 it('Should have watched settings changes', async function () {
191 this.timeout(10000)
192
89d241a7 193 await server.servers.waitUntilLog('Settings changed!')
a5896799
C
194 })
195
09071200
C
196 it('Should get a plugin and a theme', async function () {
197 {
ae2abfd3 198 const plugin = await command.get({ npmName: 'peertube-plugin-hello-world' })
09071200
C
199
200 expect(plugin.type).to.equal(PluginType.PLUGIN)
201 expect(plugin.name).to.equal('hello-world')
202 expect(plugin.description).to.exist
203 expect(plugin.homepage).to.exist
204 expect(plugin.uninstalled).to.be.false
205 expect(plugin.enabled).to.be.true
206 expect(plugin.description).to.exist
207 expect(plugin.version).to.exist
208 expect(plugin.peertubeEngine).to.exist
209 expect(plugin.createdAt).to.exist
210
211 expect(plugin.settings).to.not.be.undefined
212 expect(plugin.settings['admin-name']).to.equal('Cid')
213 }
214
215 {
ae2abfd3 216 const plugin = await command.get({ npmName: 'peertube-theme-background-red' })
9b474844 217
09071200
C
218 expect(plugin.type).to.equal(PluginType.THEME)
219 expect(plugin.name).to.equal('background-red')
220 expect(plugin.description).to.exist
221 expect(plugin.homepage).to.exist
222 expect(plugin.uninstalled).to.be.false
223 expect(plugin.enabled).to.be.true
224 expect(plugin.description).to.exist
225 expect(plugin.version).to.exist
226 expect(plugin.peertubeEngine).to.exist
227 expect(plugin.createdAt).to.exist
228
229 expect(plugin.settings).to.be.null
230 }
9b474844
C
231 })
232
233 it('Should update the plugin and the theme', async function () {
2769876f 234 this.timeout(180000)
09071200
C
235
236 // Wait the scheduler that get the latest plugins versions
237 await wait(6000)
238
2769876f
C
239 async function testUpdate (type: 'plugin' | 'theme', name: string) {
240 // Fake update our plugin version
241 await server.sql.setPluginVersion(name, '0.0.1')
09071200 242
2769876f
C
243 // Fake update package.json
244 const packageJSON = await command.getPackageJSON(`peertube-${type}-${name}`)
245 const oldVersion = packageJSON.version
09071200 246
2769876f
C
247 packageJSON.version = '0.0.1'
248 await command.updatePackageJSON(`peertube-${type}-${name}`, packageJSON)
09071200 249
2769876f
C
250 // Restart the server to take into account this change
251 await killallServers([ server ])
252 await server.run()
09071200 253
2769876f
C
254 const checkConfig = async (version: string) => {
255 for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
256 expect(config[type].registered.find(r => r.name === name).version).to.equal(version)
257 }
258 }
09071200 259
2769876f
C
260 const getPluginFromAPI = async () => {
261 const body = await command.list({ pluginType: type === 'plugin' ? PluginType.PLUGIN : PluginType.THEME })
09071200 262
2769876f
C
263 return body.data.find(p => p.name === name)
264 }
09071200 265
2769876f
C
266 {
267 const plugin = await getPluginFromAPI()
268 expect(plugin.version).to.equal('0.0.1')
269 expect(plugin.latestVersion).to.exist
270 expect(plugin.latestVersion).to.not.equal('0.0.1')
271
272 await checkConfig('0.0.1')
273 }
274
275 {
276 await command.update({ npmName: `peertube-${type}-${name}` })
09071200 277
2769876f
C
278 const plugin = await getPluginFromAPI()
279 expect(plugin.version).to.equal(oldVersion)
09071200 280
2769876f
C
281 const updatedPackageJSON = await command.getPackageJSON(`peertube-${type}-${name}`)
282 expect(updatedPackageJSON.version).to.equal(oldVersion)
283
284 await checkConfig(oldVersion)
285 }
09071200 286 }
2769876f
C
287
288 await testUpdate('theme', 'background-red')
289 await testUpdate('plugin', 'hello-world')
9b474844
C
290 })
291
292 it('Should uninstall the plugin', async function () {
ae2abfd3 293 await command.uninstall({ npmName: 'peertube-plugin-hello-world' })
09071200 294
ae2abfd3
C
295 const body = await command.list({ pluginType: PluginType.PLUGIN })
296 expect(body.total).to.equal(0)
297 expect(body.data).to.have.lengthOf(0)
9b474844
C
298 })
299
9b474844 300 it('Should list uninstalled plugins', async function () {
ae2abfd3
C
301 const body = await command.list({ pluginType: PluginType.PLUGIN, uninstalled: true })
302 expect(body.total).to.equal(1)
303 expect(body.data).to.have.lengthOf(1)
09071200 304
ae2abfd3 305 const plugin = body.data[0]
09071200
C
306 expect(plugin.name).to.equal('hello-world')
307 expect(plugin.enabled).to.be.false
308 expect(plugin.uninstalled).to.be.true
9b474844
C
309 })
310
311 it('Should uninstall the theme', async function () {
ae2abfd3 312 await command.uninstall({ npmName: 'peertube-theme-background-red' })
9b474844
C
313 })
314
315 it('Should have updated the configuration', async function () {
2769876f
C
316 for (const config of [ await server.config.getConfig(), await server.config.getIndexHTMLConfig() ]) {
317 expect(config.theme.default).to.equal('default')
09071200 318
2769876f
C
319 const theme = config.theme.registered.find(r => r.name === 'background-red')
320 expect(theme).to.be.undefined
09071200 321
2769876f
C
322 const plugin = config.plugin.registered.find(r => r.name === 'hello-world')
323 expect(plugin).to.be.undefined
324 }
09071200
C
325 })
326
327 it('Should have updated the user theme', async function () {
89d241a7 328 const user = await server.users.getMyInfo()
7926c5f9 329 expect(user.theme).to.equal('instance-default')
9b474844
C
330 })
331
9c2e051c
C
332 it('Should not install a broken plugin', async function () {
333 this.timeout(60000)
334
335 async function check () {
ae2abfd3
C
336 const body = await command.list({ pluginType: PluginType.PLUGIN })
337 const plugins = body.data
9c2e051c
C
338 expect(plugins.find(p => p.name === 'test-broken')).to.not.exist
339 }
340
ae2abfd3
C
341 await command.install({
342 path: PluginsCommand.getPluginTestPath('-broken'),
9c2e051c
C
343 expectedStatus: HttpStatusCode.BAD_REQUEST_400
344 })
345
346 await check()
347
9293139f 348 await killallServers([ server ])
254d3579 349 await server.run()
9c2e051c
C
350
351 await check()
352 })
353
c795e196 354 it('Should rebuild native modules on Node ABI change', async function () {
c543e414 355 this.timeout(60000)
94278907
C
356
357 const removeNativeModule = async () => {
358 await remove(join(baseNativeModule, 'build'))
359 await remove(join(baseNativeModule, 'prebuilds'))
360 }
361
c795e196
C
362 await command.install({ path: PluginsCommand.getPluginTestPath('-native') })
363
364 await makeGetRequest({
365 url: server.url,
366 path: '/plugins/test-native/router',
367 expectedStatus: HttpStatusCode.NO_CONTENT_204
368 })
369
370 const query = `UPDATE "application" SET "nodeABIVersion" = 1`
371 await server.sql.updateQuery(query)
372
373 const baseNativeModule = server.servers.buildDirectory(join('plugins', 'node_modules', 'a-native-example'))
c795e196 374
94278907 375 await removeNativeModule()
c795e196
C
376 await server.kill()
377 await server.run()
378
c543e414
C
379 await wait(3000)
380
94278907
C
381 expect(await pathExists(join(baseNativeModule, 'build'))).to.be.true
382 expect(await pathExists(join(baseNativeModule, 'prebuilds'))).to.be.true
c795e196
C
383
384 await makeGetRequest({
385 url: server.url,
386 path: '/plugins/test-native/router',
387 expectedStatus: HttpStatusCode.NO_CONTENT_204
388 })
94278907
C
389
390 await removeNativeModule()
391
392 await server.kill()
393 await server.run()
394
395 expect(await pathExists(join(baseNativeModule, 'build'))).to.be.false
396 expect(await pathExists(join(baseNativeModule, 'prebuilds'))).to.be.false
397
398 await makeGetRequest({
399 url: server.url,
400 path: '/plugins/test-native/router',
401 expectedStatus: HttpStatusCode.NOT_FOUND_404
402 })
c795e196
C
403 })
404
9b474844
C
405 after(async function () {
406 await cleanupTests([ server ])
407 })
408})