Barazo AppView backend barazo.forum
at main 153 lines 4.4 kB view raw
1import { describe, expect, it } from 'vitest' 2 3import { pluginManifestSchema } from '../../../src/validation/plugin-manifest.js' 4 5const VALID_MANIFEST = { 6 name: '@barazo/plugin-signatures', 7 displayName: 'User Signatures', 8 version: '1.0.0', 9 description: 'Portable user signatures with per-community overrides', 10 barazoVersion: '^1.0.0', 11 source: 'core', 12 category: 'social', 13 author: { name: 'Barazo', url: 'https://barazo.forum' }, 14 license: 'MIT', 15 permissions: { 16 backend: ['db:write:plugin_signatures', 'pds:read', 'pds:write'], 17 frontend: ['ui:inject:settings-community', 'ui:inject:post-content'], 18 }, 19} 20 21describe('pluginManifestSchema', () => { 22 it('validates a complete manifest with all fields', () => { 23 const complete = { 24 ...VALID_MANIFEST, 25 lexicons: ['forum.barazo.plugin.signatures'], 26 dependencies: ['@barazo/plugin-profiles'], 27 settings: { 28 maxLength: { 29 type: 'number', 30 label: 'Max signature length', 31 description: 'Maximum character count for signatures', 32 default: 200, 33 min: 50, 34 max: 1000, 35 }, 36 }, 37 hooks: { 38 onInstall: './hooks/install.js', 39 onUninstall: './hooks/uninstall.js', 40 onEnable: './hooks/enable.js', 41 onDisable: './hooks/disable.js', 42 onProfileSync: './hooks/profile-sync.js', 43 }, 44 backend: { 45 routes: './routes/index.js', 46 migrations: './migrations/', 47 }, 48 frontend: { 49 register: './frontend/register.js', 50 }, 51 } 52 53 const result = pluginManifestSchema.safeParse(complete) 54 expect(result.success).toBe(true) 55 }) 56 57 it('validates a minimal manifest with only required fields', () => { 58 const result = pluginManifestSchema.safeParse(VALID_MANIFEST) 59 expect(result.success).toBe(true) 60 }) 61 62 it('rejects an empty object', () => { 63 const result = pluginManifestSchema.safeParse({}) 64 expect(result.success).toBe(false) 65 }) 66 67 it('rejects an invalid source value', () => { 68 const result = pluginManifestSchema.safeParse({ 69 ...VALID_MANIFEST, 70 source: 'unknown', 71 }) 72 expect(result.success).toBe(false) 73 }) 74 75 it('rejects an invalid version (not semver)', () => { 76 const result = pluginManifestSchema.safeParse({ 77 ...VALID_MANIFEST, 78 version: 'v1.0', 79 }) 80 expect(result.success).toBe(false) 81 }) 82 83 it('accepts a manifest with all 4 settings types', () => { 84 const result = pluginManifestSchema.safeParse({ 85 ...VALID_MANIFEST, 86 settings: { 87 enabled: { 88 type: 'boolean', 89 label: 'Enabled', 90 default: true, 91 }, 92 prefix: { 93 type: 'string', 94 label: 'Prefix', 95 description: 'Text shown before the signature', 96 default: '--', 97 placeholder: 'Enter prefix...', 98 }, 99 maxLength: { 100 type: 'number', 101 label: 'Max length', 102 default: 200, 103 min: 1, 104 max: 5000, 105 }, 106 position: { 107 type: 'select', 108 label: 'Display position', 109 default: 'bottom', 110 options: ['top', 'bottom'], 111 }, 112 }, 113 }) 114 expect(result.success).toBe(true) 115 }) 116 117 it('accepts a manifest with hooks', () => { 118 const result = pluginManifestSchema.safeParse({ 119 ...VALID_MANIFEST, 120 hooks: { 121 onInstall: './hooks/install.js', 122 onEnable: './hooks/enable.js', 123 }, 124 }) 125 expect(result.success).toBe(true) 126 }) 127 128 it('accepts a manifest with backend and frontend entry points', () => { 129 const result = pluginManifestSchema.safeParse({ 130 ...VALID_MANIFEST, 131 backend: { routes: './routes/index.js', migrations: './migrations/' }, 132 frontend: { register: './frontend/register.js' }, 133 }) 134 expect(result.success).toBe(true) 135 }) 136 137 it('accepts a manifest with dependencies and lexicons', () => { 138 const result = pluginManifestSchema.safeParse({ 139 ...VALID_MANIFEST, 140 dependencies: ['@barazo/plugin-profiles'], 141 lexicons: ['forum.barazo.plugin.signatures'], 142 }) 143 expect(result.success).toBe(true) 144 }) 145 146 it('rejects a name that does not match plugin naming convention', () => { 147 const result = pluginManifestSchema.safeParse({ 148 ...VALID_MANIFEST, 149 name: 'random-package', 150 }) 151 expect(result.success).toBe(false) 152 }) 153})