mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
- Introduced `specVersion` and `version` fields to the plugin and marketplace schemas, ensuring better versioning and compatibility tracking. - Updated various components and functions to handle the new fields, including database migrations, plugin snapshots, and marketplace management. - Enhanced tests to validate the presence and correctness of the new fields in plugin manifests and marketplace entries. - Improved documentation to reflect the changes in schema requirements and provide guidance on the new versioning system. This update strengthens the plugin ecosystem by providing clear versioning, enhancing the reliability and maintainability of plugins and marketplaces.
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { parseManifest } from '../src/parsers/manifest';
|
|
import { parseMarketplace } from '../src/parsers/marketplace';
|
|
import { parseFrontmatter } from '../src/parsers/frontmatter';
|
|
|
|
describe('parseManifest', () => {
|
|
it('accepts the minimal sidecar shape', () => {
|
|
const result = parseManifest(JSON.stringify({
|
|
name: 'sample-plugin',
|
|
version: '1.0.0',
|
|
}));
|
|
expect(result.ok).toBe(true);
|
|
if (result.ok) {
|
|
expect(result.manifest.name).toBe('sample-plugin');
|
|
expect(result.manifest.version).toBe('1.0.0');
|
|
}
|
|
});
|
|
|
|
it('rejects an invalid name', () => {
|
|
const result = parseManifest(JSON.stringify({
|
|
name: 'Sample Plugin!',
|
|
version: '1.0.0',
|
|
}));
|
|
expect(result.ok).toBe(false);
|
|
});
|
|
|
|
it('preserves unknown forward-compatible fields', () => {
|
|
const result = parseManifest(JSON.stringify({
|
|
name: 'sample-plugin',
|
|
version: '1.0.0',
|
|
futureField: { hello: 'world' },
|
|
}));
|
|
expect(result.ok).toBe(true);
|
|
if (result.ok) {
|
|
expect((result.manifest as Record<string, unknown>).futureField).toEqual({ hello: 'world' });
|
|
}
|
|
});
|
|
|
|
it('accepts localized use-case queries', () => {
|
|
const result = parseManifest(JSON.stringify({
|
|
name: 'sample-plugin',
|
|
version: '1.0.0',
|
|
od: {
|
|
useCase: {
|
|
query: {
|
|
en: 'Make a brief.',
|
|
'zh-CN': '写一份简报。',
|
|
},
|
|
},
|
|
},
|
|
}));
|
|
|
|
expect(result.ok).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('parseMarketplace', () => {
|
|
it('accepts a tiny catalog', () => {
|
|
const result = parseMarketplace(JSON.stringify({
|
|
specVersion: '1.0.0',
|
|
name: 'open-design-official',
|
|
version: '1.0.0',
|
|
plugins: [{ name: 'make-a-deck', source: 'github:open-design/plugins/make-a-deck', version: '0.1.0' }],
|
|
}));
|
|
expect(result.ok).toBe(true);
|
|
});
|
|
|
|
it('rejects when catalog version is missing', () => {
|
|
const result = parseMarketplace(JSON.stringify({
|
|
name: 'no-version',
|
|
plugins: [{ name: 'make-a-deck', source: 'github:open-design/plugins/make-a-deck', version: '0.1.0' }],
|
|
}));
|
|
expect(result.ok).toBe(false);
|
|
});
|
|
|
|
it('rejects when plugin entry version is missing', () => {
|
|
const result = parseMarketplace(JSON.stringify({
|
|
name: 'missing-plugin-version',
|
|
version: '1.0.0',
|
|
plugins: [{ name: 'make-a-deck', source: 'github:open-design/plugins/make-a-deck' }],
|
|
}));
|
|
expect(result.ok).toBe(false);
|
|
});
|
|
|
|
it('rejects when plugins is missing', () => {
|
|
const result = parseMarketplace(JSON.stringify({ name: 'no-plugins', version: '1.0.0' }));
|
|
expect(result.ok).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('parseFrontmatter', () => {
|
|
it('parses a single-line description', () => {
|
|
const { data, body } = parseFrontmatter('---\nname: foo\ndescription: hello\n---\nbody');
|
|
expect(data['name']).toBe('foo');
|
|
expect(data['description']).toBe('hello');
|
|
expect(body).toBe('body');
|
|
});
|
|
|
|
it('parses block-literal descriptions', () => {
|
|
const src = '---\nname: foo\ndescription: |\n line 1\n line 2\n---\nbody';
|
|
const { data } = parseFrontmatter(src);
|
|
expect(data['description']).toBe('line 1\nline 2');
|
|
});
|
|
|
|
it('returns empty data when no frontmatter delimiter is present', () => {
|
|
const { data, body } = parseFrontmatter('# heading');
|
|
expect(Object.keys(data)).toHaveLength(0);
|
|
expect(body).toBe('# heading');
|
|
});
|
|
});
|