Skip to main content
Glama

SFCC Development MCP Server

by taurgis
class-name-resolver.test.ts•16.9 kB
import { ClassNameResolver } from '../src/clients/docs/class-name-resolver.js'; describe('ClassNameResolver', () => { describe('normalizeClassName', () => { it('should convert dot notation to underscore notation for package names', () => { expect(ClassNameResolver.normalizeClassName('dw.content.ContentMgr')).toBe('dw_content.ContentMgr'); expect(ClassNameResolver.normalizeClassName('dw.catalog.Product')).toBe('dw_catalog.Product'); expect(ClassNameResolver.normalizeClassName('dw.system.Site')).toBe('dw_system.Site'); }); it('should handle multi-level package names correctly', () => { expect(ClassNameResolver.normalizeClassName('dw.order.hooks.OrderHooks')).toBe('dw_order_hooks.OrderHooks'); expect(ClassNameResolver.normalizeClassName('dw.extensions.paymentrequest.PaymentRequest')).toBe('dw_extensions_paymentrequest.PaymentRequest'); }); it('should leave underscore notation unchanged', () => { expect(ClassNameResolver.normalizeClassName('dw_content.ContentMgr')).toBe('dw_content.ContentMgr'); expect(ClassNameResolver.normalizeClassName('dw_catalog.Product')).toBe('dw_catalog.Product'); expect(ClassNameResolver.normalizeClassName('dw_system.Site')).toBe('dw_system.Site'); }); it('should leave simple class names unchanged', () => { expect(ClassNameResolver.normalizeClassName('ContentMgr')).toBe('ContentMgr'); expect(ClassNameResolver.normalizeClassName('Product')).toBe('Product'); expect(ClassNameResolver.normalizeClassName('String')).toBe('String'); }); it('should handle TopLevel classes correctly', () => { expect(ClassNameResolver.normalizeClassName('TopLevel.String')).toBe('TopLevel.String'); expect(ClassNameResolver.normalizeClassName('TopLevel.Number')).toBe('TopLevel.Number'); }); it('should handle mixed notation gracefully', () => { // If already has underscores, don't convert dots expect(ClassNameResolver.normalizeClassName('dw_content.ContentMgr.SubClass')).toBe('dw_content.ContentMgr.SubClass'); }); it('should handle empty and edge case inputs', () => { expect(ClassNameResolver.normalizeClassName('')).toBe(''); expect(ClassNameResolver.normalizeClassName('.')).toBe('.'); expect(ClassNameResolver.normalizeClassName('_')).toBe('_'); expect(ClassNameResolver.normalizeClassName('a')).toBe('a'); }); it('should handle special characters', () => { expect(ClassNameResolver.normalizeClassName('dw.test-package.TestClass')).toBe('dw_test-package.TestClass'); expect(ClassNameResolver.normalizeClassName('dw.test123.TestClass')).toBe('dw_test123.TestClass'); }); }); describe('extractSimpleClassName', () => { it('should extract simple class name from fully qualified names', () => { expect(ClassNameResolver.extractSimpleClassName('dw_content.ContentMgr')).toBe('ContentMgr'); expect(ClassNameResolver.extractSimpleClassName('dw_catalog.Product')).toBe('Product'); expect(ClassNameResolver.extractSimpleClassName('dw_system.Site')).toBe('Site'); }); it('should handle dot notation input', () => { expect(ClassNameResolver.extractSimpleClassName('dw.content.ContentMgr')).toBe('ContentMgr'); expect(ClassNameResolver.extractSimpleClassName('dw.catalog.Product')).toBe('Product'); }); it('should return same value for simple class names', () => { expect(ClassNameResolver.extractSimpleClassName('ContentMgr')).toBe('ContentMgr'); expect(ClassNameResolver.extractSimpleClassName('Product')).toBe('Product'); expect(ClassNameResolver.extractSimpleClassName('String')).toBe('String'); }); it('should handle multi-level packages', () => { expect(ClassNameResolver.extractSimpleClassName('dw_order_hooks.OrderHooks')).toBe('OrderHooks'); expect(ClassNameResolver.extractSimpleClassName('dw.extensions.paymentrequest.PaymentRequest')).toBe('PaymentRequest'); }); it('should handle TopLevel classes', () => { expect(ClassNameResolver.extractSimpleClassName('TopLevel.String')).toBe('String'); expect(ClassNameResolver.extractSimpleClassName('TopLevel.Number')).toBe('Number'); }); it('should handle edge cases', () => { expect(ClassNameResolver.extractSimpleClassName('')).toBe(''); expect(ClassNameResolver.extractSimpleClassName('.')).toBe(''); expect(ClassNameResolver.extractSimpleClassName('.ClassName')).toBe('ClassName'); expect(ClassNameResolver.extractSimpleClassName('Package.')).toBe(''); }); it('should handle multiple dots correctly', () => { expect(ClassNameResolver.extractSimpleClassName('a.b.c.d.FinalClass')).toBe('FinalClass'); expect(ClassNameResolver.extractSimpleClassName('..ClassName')).toBe('ClassName'); }); }); describe('toOfficialFormat', () => { it('should convert underscores to dots in package names', () => { expect(ClassNameResolver.toOfficialFormat('dw_content.ContentMgr')).toBe('dw.content.ContentMgr'); expect(ClassNameResolver.toOfficialFormat('dw_catalog.Product')).toBe('dw.catalog.Product'); expect(ClassNameResolver.toOfficialFormat('dw_system.Site')).toBe('dw.system.Site'); }); it('should handle multi-level package names', () => { expect(ClassNameResolver.toOfficialFormat('dw_order_hooks.OrderHooks')).toBe('dw.order.hooks.OrderHooks'); expect(ClassNameResolver.toOfficialFormat('dw_extensions_paymentrequest.PaymentRequest')).toBe('dw.extensions.paymentrequest.PaymentRequest'); }); it('should handle TopLevel classes specially', () => { expect(ClassNameResolver.toOfficialFormat('TopLevel.String')).toBe('TopLevel.String'); expect(ClassNameResolver.toOfficialFormat('TopLevel.Number')).toBe('TopLevel.Number'); }); it('should handle simple class names without packages', () => { expect(ClassNameResolver.toOfficialFormat('ContentMgr')).toBe('ContentMgr'); expect(ClassNameResolver.toOfficialFormat('Product')).toBe('Product'); expect(ClassNameResolver.toOfficialFormat('String')).toBe('String'); }); it('should handle already converted class names', () => { expect(ClassNameResolver.toOfficialFormat('dw.content.ContentMgr')).toBe('dw.content.ContentMgr'); expect(ClassNameResolver.toOfficialFormat('dw.catalog.Product')).toBe('dw.catalog.Product'); }); it('should handle edge cases', () => { expect(ClassNameResolver.toOfficialFormat('')).toBe(''); expect(ClassNameResolver.toOfficialFormat('_')).toBe('.'); expect(ClassNameResolver.toOfficialFormat('__')).toBe('..'); expect(ClassNameResolver.toOfficialFormat('test_')).toBe('test.'); expect(ClassNameResolver.toOfficialFormat('_test')).toBe('.test'); }); it('should handle multiple underscores', () => { expect(ClassNameResolver.toOfficialFormat('dw_test_package_name.ClassName')).toBe('dw.test.package.name.ClassName'); expect(ClassNameResolver.toOfficialFormat('very_long_package_name.VeryLongClassName')).toBe('very.long.package.name.VeryLongClassName'); }); }); describe('findClassMatches', () => { let mockClassCache: Map<string, any>; beforeEach(() => { mockClassCache = new Map([ ['dw_content.ContentMgr', { className: 'ContentMgr', packageName: 'dw.content' }], ['dw_catalog.Product', { className: 'Product', packageName: 'dw.catalog' }], ['dw_system.Site', { className: 'Site', packageName: 'dw.system' }], ['TopLevel.String', { className: 'String', packageName: 'TopLevel' }], ['dw_util.StringUtils', { className: 'StringUtils', packageName: 'dw.util' }], ['dw_order.Order', { className: 'Order', packageName: 'dw.order' }], ['test_package.Product', { className: 'Product', packageName: 'test.package' }], // Duplicate class name ]); }); it('should find classes by simple class name', () => { const matches = ClassNameResolver.findClassMatches('ContentMgr', mockClassCache); expect(matches).toHaveLength(1); expect(matches[0].key).toBe('dw_content.ContentMgr'); expect(matches[0].info.className).toBe('ContentMgr'); }); it('should find classes when using fully qualified name', () => { const matches = ClassNameResolver.findClassMatches('dw_content.ContentMgr', mockClassCache); expect(matches).toHaveLength(1); expect(matches[0].key).toBe('dw_content.ContentMgr'); expect(matches[0].info.className).toBe('ContentMgr'); }); it('should find classes when using dot notation', () => { const matches = ClassNameResolver.findClassMatches('dw.content.ContentMgr', mockClassCache); expect(matches).toHaveLength(1); expect(matches[0].key).toBe('dw_content.ContentMgr'); expect(matches[0].info.className).toBe('ContentMgr'); }); it('should find multiple classes with the same simple name', () => { const matches = ClassNameResolver.findClassMatches('Product', mockClassCache); expect(matches).toHaveLength(2); const keys = matches.map(m => m.key).sort(); expect(keys).toEqual(['dw_catalog.Product', 'test_package.Product']); }); it('should return empty array for non-existent class', () => { const matches = ClassNameResolver.findClassMatches('NonExistentClass', mockClassCache); expect(matches).toHaveLength(0); }); it('should handle TopLevel classes', () => { const matches = ClassNameResolver.findClassMatches('String', mockClassCache); expect(matches).toHaveLength(1); expect(matches[0].key).toBe('TopLevel.String'); expect(matches[0].info.className).toBe('String'); }); it('should handle empty class cache', () => { const emptyCache = new Map(); const matches = ClassNameResolver.findClassMatches('Product', emptyCache); expect(matches).toHaveLength(0); }); it('should handle edge case inputs', () => { expect(ClassNameResolver.findClassMatches('', mockClassCache)).toHaveLength(0); expect(ClassNameResolver.findClassMatches('.', mockClassCache)).toHaveLength(0); expect(ClassNameResolver.findClassMatches('Package.', mockClassCache)).toHaveLength(0); }); }); describe('resolveClassName', () => { let mockClassCache: Map<string, any>; beforeEach(() => { mockClassCache = new Map([ ['dw_content.ContentMgr', { className: 'ContentMgr', packageName: 'dw.content', content: 'content1' }], ['dw_catalog.Product', { className: 'Product', packageName: 'dw.catalog', content: 'content2' }], ['dw_system.Site', { className: 'Site', packageName: 'dw.system', content: 'content3' }], ['TopLevel.String', { className: 'String', packageName: 'TopLevel', content: 'content4' }], ['dw_util.StringUtils', { className: 'StringUtils', packageName: 'dw.util', content: 'content5' }], ['test_package.Product', { className: 'Product', packageName: 'test.package', content: 'content6' }], ]); }); it('should find exact matches using underscore notation', () => { const result = ClassNameResolver.resolveClassName('dw_content.ContentMgr', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('dw_content.ContentMgr'); expect(result!.info.className).toBe('ContentMgr'); expect(result!.info.content).toBe('content1'); }); it('should find exact matches using dot notation', () => { const result = ClassNameResolver.resolveClassName('dw.content.ContentMgr', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('dw_content.ContentMgr'); expect(result!.info.className).toBe('ContentMgr'); expect(result!.info.content).toBe('content1'); }); it('should fallback to simple name matching when exact match not found', () => { const result = ClassNameResolver.resolveClassName('Site', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('dw_system.Site'); expect(result!.info.className).toBe('Site'); }); it('should handle TopLevel classes correctly', () => { const result = ClassNameResolver.resolveClassName('String', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('TopLevel.String'); expect(result!.info.className).toBe('String'); }); it('should return null for non-existent classes', () => { const result = ClassNameResolver.resolveClassName('NonExistentClass', mockClassCache); expect(result).toBeNull(); }); it('should throw error when multiple classes match simple name', () => { expect(() => { ClassNameResolver.resolveClassName('Product', mockClassCache); }).toThrow('Multiple classes found with name "Product": dw_catalog.Product, test_package.Product'); }); it('should prioritize exact matches over simple name matches', () => { const result = ClassNameResolver.resolveClassName('dw_catalog.Product', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('dw_catalog.Product'); expect(result!.info.packageName).toBe('dw.catalog'); }); it('should handle empty cache gracefully', () => { const emptyCache = new Map(); const result = ClassNameResolver.resolveClassName('Product', emptyCache); expect(result).toBeNull(); }); it('should handle edge case inputs', () => { expect(ClassNameResolver.resolveClassName('', mockClassCache)).toBeNull(); expect(ClassNameResolver.resolveClassName('.', mockClassCache)).toBeNull(); expect(ClassNameResolver.resolveClassName('Package.', mockClassCache)).toBeNull(); }); it('should handle normalization of input before matching', () => { // Test that dot notation gets normalized to underscore before exact matching const result = ClassNameResolver.resolveClassName('dw.util.StringUtils', mockClassCache); expect(result).not.toBeNull(); expect(result!.key).toBe('dw_util.StringUtils'); expect(result!.info.className).toBe('StringUtils'); }); }); describe('integration scenarios', () => { let mockClassCache: Map<string, any>; beforeEach(() => { mockClassCache = new Map([ ['dw_content.ContentMgr', { className: 'ContentMgr', packageName: 'dw.content' }], ['dw_catalog.Product', { className: 'Product', packageName: 'dw.catalog' }], ['TopLevel.String', { className: 'String', packageName: 'TopLevel' }], ['dw_system.Pipeline', { className: 'Pipeline', packageName: 'dw.system' }], ]); }); it('should handle complete workflow: normalize -> resolve -> convert to official', () => { const inputClassName = 'dw.content.ContentMgr'; // Step 1: Normalize const normalized = ClassNameResolver.normalizeClassName(inputClassName); expect(normalized).toBe('dw_content.ContentMgr'); // Step 2: Resolve const resolved = ClassNameResolver.resolveClassName(normalized, mockClassCache); expect(resolved).not.toBeNull(); expect(resolved!.key).toBe('dw_content.ContentMgr'); // Step 3: Convert to official format const official = ClassNameResolver.toOfficialFormat(resolved!.key); expect(official).toBe('dw.content.ContentMgr'); }); it('should handle round-trip conversions correctly', () => { const testCases = [ 'dw.content.ContentMgr', 'dw_content.ContentMgr', 'TopLevel.String', 'ContentMgr', ]; testCases.forEach(testCase => { const normalized = ClassNameResolver.normalizeClassName(testCase); const official = ClassNameResolver.toOfficialFormat(normalized); const backToNormalized = ClassNameResolver.normalizeClassName(official); expect(backToNormalized).toBe(normalized); }); }); it('should maintain consistency across all methods', () => { const inputClass = 'dw.catalog.Product'; // All methods should work together consistently const normalized = ClassNameResolver.normalizeClassName(inputClass); const simple = ClassNameResolver.extractSimpleClassName(normalized); const matches = ClassNameResolver.findClassMatches(simple, mockClassCache); const resolved = ClassNameResolver.resolveClassName(inputClass, mockClassCache); const official = ClassNameResolver.toOfficialFormat(normalized); expect(normalized).toBe('dw_catalog.Product'); expect(simple).toBe('Product'); expect(matches).toHaveLength(1); expect(matches[0].key).toBe('dw_catalog.Product'); expect(resolved).not.toBeNull(); expect(resolved!.key).toBe('dw_catalog.Product'); expect(official).toBe('dw.catalog.Product'); }); }); });

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/taurgis/sfcc-dev-mcp'

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