- GET /plugins (backend.view_plugins, superusers always pass) lists the plugins from party.Installed, or party.Activated IDs for older builds, with the built framework version and whether the registry is configured - Settings -> System -> Plugins entry with the new SettingsEntry.path, added only for principals allowed to open it - PluginsView at /system/plugins with an Installed tab (reka-ui Tabs); settings panel, rail, breadcrumbs and page title know the route - OpenAPI and SPA types regenerated; contract, token-class and conformance inventories list the route; en/pl strings; docs
111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import { enableAutoUnmount } from '@vue/test-utils'
|
|
import PluginsView from '../../src/views/PluginsView.vue'
|
|
import { settingsPath } from '../../src/state/useSettings'
|
|
import type { InstalledPlugin, PluginsOverview, SettingsEntry } from '../../src/api/types'
|
|
import { API, mountApp, requestsTo, resetState, type Route } from '../helpers'
|
|
|
|
const PLUGINS = `${API}/plugins`
|
|
|
|
function installed(overrides: Partial<InstalledPlugin> & { id: string }): InstalledPlugin {
|
|
return {
|
|
name: '',
|
|
description: '',
|
|
version: '',
|
|
source: '',
|
|
module: '',
|
|
package: '',
|
|
listed: false,
|
|
latest: '',
|
|
latestFramework: '',
|
|
updateAvailable: false,
|
|
updateCommand: '',
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
function overview(overrides: Partial<PluginsOverview> = {}): PluginsOverview {
|
|
return {
|
|
framework: 'v0.6.0',
|
|
registry: { enabled: false, status: 'disabled' },
|
|
plugins: [
|
|
installed({
|
|
id: 'acme.blog',
|
|
name: 'Blog',
|
|
description: 'Posts <b>and</b> categories.',
|
|
version: 'v0.1.0',
|
|
source: 'module',
|
|
module: 'example.test/acme-blog',
|
|
package: 'example.test/acme-blog',
|
|
}),
|
|
installed({ id: 'acme.local', source: 'local' }),
|
|
],
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
const envelope = (data: unknown) => ({ body: { data, meta: {} } })
|
|
|
|
async function openPlugins(data: PluginsOverview = overview(), routes: Record<string, Route> = {}) {
|
|
return mountApp('/system/plugins', { [`GET ${PLUGINS}`]: envelope(data), ...routes }, { attach: true })
|
|
}
|
|
|
|
beforeEach(() => {
|
|
resetState()
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = ''
|
|
})
|
|
|
|
enableAutoUnmount(afterEach)
|
|
|
|
describe('PluginsView', () => {
|
|
it('renders the installed plugins from GET /plugins', async () => {
|
|
const { wrapper, calls } = await openPlugins()
|
|
expect(wrapper.findComponent(PluginsView).exists()).toBe(true)
|
|
expect(requestsTo(calls, 'GET', PLUGINS)).toHaveLength(1)
|
|
expect(wrapper.find('h1').text()).toBe('Wtyczki')
|
|
expect(wrapper.find('[data-plugins-framework]').text()).toBe('Framework v0.6.0')
|
|
|
|
const rows = wrapper.findAll('[data-plugin]')
|
|
expect(rows.map((row) => row.attributes('data-plugin'))).toEqual(['acme.blog', 'acme.local'])
|
|
const blog = rows[0]!
|
|
expect(blog.find('[data-plugin-name]').text()).toBe('Blog')
|
|
expect(blog.find('[data-plugin-version]').text()).toBe('v0.1.0')
|
|
expect(blog.find('[data-plugin-source]').text()).toBe('Moduł Go')
|
|
// Registry and plugin text is text, never HTML.
|
|
expect(blog.find('[data-plugin-description]').text()).toBe('Posts <b>and</b> categories.')
|
|
expect(blog.find('b').exists()).toBe(false)
|
|
|
|
const local = rows[1]!
|
|
expect(local.find('[data-plugin-name]').text()).toBe('acme.local')
|
|
expect(local.find('[data-plugin-version]').text()).toBe('Brak wersji')
|
|
expect(local.find('[data-plugin-source]').text()).toBe('W aplikacji')
|
|
})
|
|
|
|
it('shows an error when the list cannot be loaded', async () => {
|
|
const { wrapper } = await openPlugins(overview(), {
|
|
[`GET ${PLUGINS}`]: { status: 403, body: { error: { code: 'forbidden', message: 'Forbidden', details: {} } } },
|
|
})
|
|
expect(wrapper.find('[data-plugins-failed]').exists()).toBe(true)
|
|
expect(wrapper.findAll('[data-plugin]')).toHaveLength(0)
|
|
})
|
|
|
|
it('opens from the settings entry path', () => {
|
|
const entry: SettingsEntry = {
|
|
code: 'plugins',
|
|
label: 'Wtyczki',
|
|
description: '',
|
|
category: 'System',
|
|
icon: 'puzzle',
|
|
order: 120,
|
|
keywords: [],
|
|
model: '',
|
|
controller: '',
|
|
path: '/system/plugins',
|
|
}
|
|
expect(settingsPath(entry)).toBe('/system/plugins')
|
|
})
|
|
})
|