Skip to main content
Glama
version-matcher.test.ts6.46 kB
/** * Version Matcher Tests * * Tests for plugin version matching utilities. * * @package WP_Navigator_MCP * @since 2.1.0 */ import { describe, it, expect } from 'vitest'; import { isVersionCompatible, matchCookbooksToPlugins, type PluginInfo, } from './version-matcher.js'; import type { LoadedCookbook } from './types.js'; // ============================================================================= // isVersionCompatible Tests // ============================================================================= describe('isVersionCompatible', () => { describe('basic version checks', () => { it('should return true when no constraints provided', () => { expect(isVersionCompatible('1.0.0')).toBe(true); expect(isVersionCompatible('5.0.0', undefined, undefined)).toBe(true); }); it('should return true when plugin version is undefined', () => { expect(isVersionCompatible(undefined, '1.0.0', '2.0.0')).toBe(true); }); it('should return true for invalid version format', () => { expect(isVersionCompatible('invalid', '1.0.0')).toBe(true); }); }); describe('minimum version checks', () => { it('should return true when version meets minimum', () => { expect(isVersionCompatible('3.20.0', '3.20.0')).toBe(true); expect(isVersionCompatible('3.21.0', '3.20.0')).toBe(true); expect(isVersionCompatible('4.0.0', '3.20.0')).toBe(true); }); it('should return false when version below minimum', () => { expect(isVersionCompatible('3.19.0', '3.20.0')).toBe(false); expect(isVersionCompatible('2.0.0', '3.0.0')).toBe(false); expect(isVersionCompatible('3.19.9', '3.20.0')).toBe(false); }); }); describe('maximum version checks', () => { it('should return true when version within maximum', () => { expect(isVersionCompatible('3.20.0', undefined, '4.0.0')).toBe(true); expect(isVersionCompatible('3.99.99', undefined, '4.0.0')).toBe(true); }); it('should return false when version exceeds maximum', () => { expect(isVersionCompatible('4.1.0', undefined, '4.0.0')).toBe(false); expect(isVersionCompatible('5.0.0', undefined, '4.0.0')).toBe(false); }); }); describe('combined min/max checks', () => { it('should return true when version in range', () => { expect(isVersionCompatible('3.21.0', '3.20.0', '4.0.0')).toBe(true); expect(isVersionCompatible('3.20.0', '3.20.0', '4.0.0')).toBe(true); expect(isVersionCompatible('4.0.0', '3.20.0', '4.0.0')).toBe(true); }); it('should return false when version out of range', () => { expect(isVersionCompatible('3.19.0', '3.20.0', '4.0.0')).toBe(false); expect(isVersionCompatible('4.1.0', '3.20.0', '4.0.0')).toBe(false); }); }); describe('edge cases', () => { it('should handle two-part versions', () => { expect(isVersionCompatible('6.0', '6.0')).toBe(true); expect(isVersionCompatible('6.1', '6.0')).toBe(true); expect(isVersionCompatible('5.9', '6.0')).toBe(false); }); it('should handle single-part versions', () => { expect(isVersionCompatible('6', '6')).toBe(true); expect(isVersionCompatible('7', '6')).toBe(true); }); it('should compare different length versions', () => { expect(isVersionCompatible('6.0.0', '6.0')).toBe(true); expect(isVersionCompatible('6.0', '6.0.0')).toBe(true); }); }); }); // ============================================================================= // matchCookbooksToPlugins Tests // ============================================================================= describe('matchCookbooksToPlugins', () => { const createCookbook = ( slug: string, minVersion?: string, maxVersion?: string ): LoadedCookbook => ({ schema_version: 1, cookbook_version: '1.0.0', plugin: { slug, name: slug.charAt(0).toUpperCase() + slug.slice(1), min_version: minVersion, max_version: maxVersion, }, capabilities: {}, source: 'bundled', sourcePath: `/test/${slug}.md`, }); it('should match plugins to cookbooks', () => { const cookbooks = new Map<string, LoadedCookbook>([ ['gutenberg', createCookbook('gutenberg', '6.0')], ['elementor', createCookbook('elementor', '3.20.0')], ]); const plugins: PluginInfo[] = [ { slug: 'gutenberg', version: '17.0.0' }, { slug: 'elementor', version: '3.21.0' }, ]; const matches = matchCookbooksToPlugins(cookbooks, plugins); expect(matches).toHaveLength(2); expect(matches[0].plugin.slug).toBe('gutenberg'); expect(matches[0].compatible).toBe(true); expect(matches[1].plugin.slug).toBe('elementor'); expect(matches[1].compatible).toBe(true); }); it('should skip plugins without cookbooks', () => { const cookbooks = new Map<string, LoadedCookbook>([['gutenberg', createCookbook('gutenberg')]]); const plugins: PluginInfo[] = [ { slug: 'gutenberg', version: '17.0.0' }, { slug: 'woocommerce', version: '8.0.0' }, { slug: 'yoast-seo', version: '21.0.0' }, ]; const matches = matchCookbooksToPlugins(cookbooks, plugins); expect(matches).toHaveLength(1); expect(matches[0].plugin.slug).toBe('gutenberg'); }); it('should mark incompatible versions', () => { const cookbooks = new Map<string, LoadedCookbook>([ ['elementor', createCookbook('elementor', '3.20.0', '4.0.0')], ]); const plugins: PluginInfo[] = [{ slug: 'elementor', version: '3.19.0' }]; const matches = matchCookbooksToPlugins(cookbooks, plugins); expect(matches).toHaveLength(1); expect(matches[0].compatible).toBe(false); expect(matches[0].reason).toContain('below minimum'); }); it('should mark version exceeds maximum', () => { const cookbooks = new Map<string, LoadedCookbook>([ ['elementor', createCookbook('elementor', '3.20.0', '4.0.0')], ]); const plugins: PluginInfo[] = [{ slug: 'elementor', version: '4.1.0' }]; const matches = matchCookbooksToPlugins(cookbooks, plugins); expect(matches).toHaveLength(1); expect(matches[0].compatible).toBe(false); expect(matches[0].reason).toContain('exceeds maximum'); }); it('should handle empty inputs', () => { expect(matchCookbooksToPlugins(new Map(), [])).toEqual([]); expect(matchCookbooksToPlugins(new Map([['test', createCookbook('test')]]), [])).toEqual([]); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/littlebearapps/wp-navigator-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server