Skip to main content
Glama
sapsystem-resources.test.ts17.5 kB
import { registerSapSystemResources } from '../../src/resources/sapsystem-resources'; import { SimplifierClient } from '../../src/client/simplifier-client'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { SAPSystem, SAPSystemListResponse } from '../../src/client/types'; // Mock the resourcesresult wrapper jest.mock('../../src/resources/resourcesresult', () => ({ wrapResourceResult: jest.fn() })); // Mock the SimplifierClient jest.mock('../../src/client/simplifier-client'); describe('SAP System Resources', () => { let mockServer: jest.Mocked<McpServer>; let mockClient: jest.Mocked<SimplifierClient>; let mockWrapResourceResult: jest.MockedFunction<any>; beforeEach(() => { // Create mock server with resource method mockServer = { resource: jest.fn(), } as any; // Create mock client mockClient = { listSapSystems: jest.fn(), getSapSystem: jest.fn(), } as any; // Get the mocked wrapResourceResult mockWrapResourceResult = require('../../src/resources/resourcesresult').wrapResourceResult; mockWrapResourceResult.mockClear(); }); afterEach(() => { jest.clearAllMocks(); }); const mockSapSystemListResponse: SAPSystemListResponse = { sapSystems: [ { name: 'DEV_SYSTEM', description: 'Development SAP System', active: true, instanceRestrictions: [], systemType: 'Development', tags: ['development', 'test'], assignedProjects: { projectsBefore: ['Project1'], projectsAfterChange: ['Project1'] }, permission: { deletable: true, editable: true }, updateInfo: { created: '2024-01-01T00:00:00Z', creator: { loginName: 'testuser', firstName: 'Test', lastName: 'User', platformDomain: 'example.com', differentPlatformDomain: false } }, referencedBy: { loginMethods: [], connectors: ['RFCConnector1'] } }, { name: 'PRD_SYSTEM', description: 'Production SAP System', active: true, instanceRestrictions: ['prod-instance'], systemType: 'Production', tags: ['production'], assignedProjects: { projectsBefore: [], projectsAfterChange: [] }, permission: { deletable: true, editable: true }, updateInfo: { created: '2024-01-15T00:00:00Z', creator: { loginName: 'admin', firstName: 'Admin', lastName: 'User', platformDomain: 'example.com', differentPlatformDomain: false } }, referencedBy: { loginMethods: [], connectors: ['RFCConnector2'] } } ] }; const mockSapSystemDetails: SAPSystem = { name: 'DEV_SYSTEM', description: 'Development SAP System', active: true, instanceRestrictions: [], systemType: 'Development', configuration: { systemId: 'DEV', systemNumber: '00', clientNumber: '100', language: 'EN', applicationServerHostname: 'sap-dev.example.com', sapRouterString: '', sncActive: false, sncPartner: '', sncSsoMode: false, sncQualityOfProtection: 3 }, tags: ['development', 'test'], assignedProjects: { projectsBefore: ['Project1'], projectsAfterChange: ['Project1'] }, permission: { deletable: true, editable: true } }; describe('Resource Registration', () => { it('should register two SAP system resources', () => { registerSapSystemResources(mockServer, mockClient); expect(mockServer.resource).toHaveBeenCalledTimes(2); }); it('should register sap-systems-list resource with correct configuration', () => { registerSapSystemResources(mockServer, mockClient); expect(mockServer.resource).toHaveBeenCalledWith( 'sap-systems-list', 'simplifier://sap-systems', expect.objectContaining({ title: 'List All SAP systems', mimeType: 'application/json', description: expect.stringContaining('# Get the list of all SAP systems') }), expect.any(Function) ); }); it('should register sap-system-details resource with correct configuration', () => { registerSapSystemResources(mockServer, mockClient); const detailsResourceCall = mockServer.resource.mock.calls.find( call => call[0] === 'sap-system-details' ); expect(detailsResourceCall).toBeDefined(); expect(detailsResourceCall![0]).toBe('sap-system-details'); expect(detailsResourceCall![2]).toMatchObject({ title: 'Get SAP System Details', mimeType: 'application/json', description: expect.stringContaining('# Get detailed configuration for a specific SAP system') }); }); }); describe('sap-systems-list resource', () => { let listHandler: Function; beforeEach(() => { registerSapSystemResources(mockServer, mockClient); const listResourceCall = mockServer.resource.mock.calls.find( call => call[0] === 'sap-systems-list' ); listHandler = listResourceCall![3] as Function; mockWrapResourceResult.mockImplementation(async (_uri: any, callback: any) => { return callback(); }); }); it('should return list of SAP systems with URIs', async () => { mockClient.listSapSystems.mockResolvedValue(mockSapSystemListResponse); const result = await listHandler(new URL('simplifier://sap-systems')); expect(mockClient.listSapSystems).toHaveBeenCalledWith( expect.stringContaining('sap-systems-list') ); expect(result).toEqual({ sapSystems: [ expect.objectContaining({ uri: 'simplifier://sap-system/DEV_SYSTEM', name: 'DEV_SYSTEM', description: 'Development SAP System' }), expect.objectContaining({ uri: 'simplifier://sap-system/PRD_SYSTEM', name: 'PRD_SYSTEM', description: 'Production SAP System' }) ], totalCount: 2, resourcePatterns: [ 'simplifier://sap-systems - List all SAP systems', 'simplifier://sap-system/{name} - Specific SAP system details' ] }); }); it('should handle empty SAP system list', async () => { mockClient.listSapSystems.mockResolvedValue({ sapSystems: [] }); const result = await listHandler(new URL('simplifier://sap-systems')); expect(result).toEqual({ sapSystems: [], totalCount: 0, resourcePatterns: [ 'simplifier://sap-systems - List all SAP systems', 'simplifier://sap-system/{name} - Specific SAP system details' ] }); }); it('should call wrapResourceResult with correct URI', async () => { mockClient.listSapSystems.mockResolvedValue(mockSapSystemListResponse); const testUri = new URL('simplifier://sap-systems'); await listHandler(testUri); expect(mockWrapResourceResult).toHaveBeenCalledWith( testUri, expect.any(Function) ); }); it('should include all SAP system properties in response', async () => { mockClient.listSapSystems.mockResolvedValue(mockSapSystemListResponse); const result = await listHandler(new URL('simplifier://sap-systems')); const firstSystem = result.sapSystems[0]; expect(firstSystem).toMatchObject({ name: 'DEV_SYSTEM', description: 'Development SAP System', active: true, systemType: 'Development', tags: ['development', 'test'], updateInfo: expect.any(Object), referencedBy: expect.any(Object) }); }); }); describe('sap-system-details resource', () => { let detailsHandler: Function; beforeEach(() => { registerSapSystemResources(mockServer, mockClient); const detailsResourceCall = mockServer.resource.mock.calls.find( call => call[0] === 'sap-system-details' ); detailsHandler = detailsResourceCall![3] as Function; mockWrapResourceResult.mockImplementation(async (_uri: any, callback: any) => { return callback(); }); }); it('should return details for a specific SAP system', async () => { mockClient.getSapSystem.mockResolvedValue(mockSapSystemDetails); const result = await detailsHandler( new URL('simplifier://sap-system/DEV_SYSTEM'), { sapSystemName: 'DEV_SYSTEM' } ); expect(mockClient.getSapSystem).toHaveBeenCalledWith( 'DEV_SYSTEM', expect.stringContaining('sap-system-details') ); expect(result).toMatchObject({ name: 'DEV_SYSTEM', description: 'Development SAP System', active: true, configuration: expect.objectContaining({ systemId: 'DEV', systemNumber: '00', clientNumber: '100', sncQualityOfProtection: 'privacy+integrity+authentication' }) }); }); it('should convert SNC quality of protection ID to string', async () => { const systemWithMaxQuality: SAPSystem = { ...mockSapSystemDetails, configuration: { ...mockSapSystemDetails.configuration, sncQualityOfProtection: 9 // maximum } }; mockClient.getSapSystem.mockResolvedValue(systemWithMaxQuality); const result = await detailsHandler( new URL('simplifier://sap-system/PRD_SYSTEM'), { sapSystemName: 'PRD_SYSTEM' } ); expect(result.configuration.sncQualityOfProtection).toBe('maximum'); }); it('should handle all SNC quality of protection levels', async () => { const testCases = [ { id: 1, expected: 'authentication' }, { id: 2, expected: 'integrity+authentication' }, { id: 3, expected: 'privacy+integrity+authentication' }, { id: 8, expected: 'default' }, { id: 9, expected: 'maximum' } ]; for (const testCase of testCases) { const systemWithQuality: SAPSystem = { ...mockSapSystemDetails, configuration: { ...mockSapSystemDetails.configuration, sncQualityOfProtection: testCase.id } }; mockClient.getSapSystem.mockResolvedValue(systemWithQuality); const result = await detailsHandler( new URL(`simplifier://sap-system/TEST_${testCase.id}`), { sapSystemName: `TEST_${testCase.id}` } ); expect(result.configuration.sncQualityOfProtection).toBe(testCase.expected); } }); it('should handle SAP system with SNC enabled', async () => { const sncSystem: SAPSystem = { ...mockSapSystemDetails, name: 'SNC_SYSTEM', configuration: { ...mockSapSystemDetails.configuration, sncActive: true, sncPartner: 'p:CN=PRD, O=MyCompany, C=US', sncSsoMode: true, sncQualityOfProtection: 9, sapRouterString: '/H/router.example.com/S/3299/H/' } }; mockClient.getSapSystem.mockResolvedValue(sncSystem); const result = await detailsHandler( new URL('simplifier://sap-system/SNC_SYSTEM'), { sapSystemName: 'SNC_SYSTEM' } ); expect(result.configuration).toMatchObject({ sncActive: true, sncPartner: 'p:CN=PRD, O=MyCompany, C=US', sncSsoMode: true, sncQualityOfProtection: 'maximum', sapRouterString: '/H/router.example.com/S/3299/H/' }); }); it('should throw error when sapSystemName is an object', async () => { await expect( detailsHandler( new URL('simplifier://sap-system/multiple'), { sapSystemName: ['System1', 'System2'] } ) ).rejects.toThrow('Only details for a single SAP system can be requested at once'); }); it('should call wrapResourceResult with correct URI', async () => { mockClient.getSapSystem.mockResolvedValue(mockSapSystemDetails); const testUri = new URL('simplifier://sap-system/DEV_SYSTEM'); await detailsHandler(testUri, { sapSystemName: 'DEV_SYSTEM' }); expect(mockWrapResourceResult).toHaveBeenCalledWith( testUri, expect.any(Function) ); }); it('should preserve all SAP system properties', async () => { const fullSystem: SAPSystem = { name: 'FULL_SYSTEM', description: 'Full SAP System with all properties', active: true, instanceRestrictions: ['instance1', 'instance2'], systemType: 'QA', configuration: { systemId: 'QAS', systemNumber: '02', clientNumber: '300', language: 'DE', applicationServerHostname: 'sap-qa.example.com', sapRouterString: '/H/router.qa/S/3299/H/', sncActive: true, sncPartner: 'p:CN=QAS, O=Company', sncSsoMode: false, sncQualityOfProtection: 2 }, tags: ['qa', 'testing', 'integration'], assignedProjects: { projectsBefore: ['OldProject'], projectsAfterChange: ['NewProject1', 'NewProject2'] }, permission: { deletable: true, editable: true } }; mockClient.getSapSystem.mockResolvedValue(fullSystem); const result = await detailsHandler( new URL('simplifier://sap-system/FULL_SYSTEM'), { sapSystemName: 'FULL_SYSTEM' } ); expect(result).toMatchObject({ name: 'FULL_SYSTEM', description: 'Full SAP System with all properties', active: true, instanceRestrictions: ['instance1', 'instance2'], systemType: 'QA', configuration: { systemId: 'QAS', systemNumber: '02', clientNumber: '300', language: 'DE', applicationServerHostname: 'sap-qa.example.com', sapRouterString: '/H/router.qa/S/3299/H/', sncActive: true, sncPartner: 'p:CN=QAS, O=Company', sncSsoMode: false, sncQualityOfProtection: 'integrity+authentication' }, tags: ['qa', 'testing', 'integration'], assignedProjects: { projectsBefore: ['OldProject'], projectsAfterChange: ['NewProject1', 'NewProject2'] }, permission: { deletable: true, editable: true } }); }); it('should handle SAP system with minimal configuration', async () => { const minimalSystem: SAPSystem = { name: 'MINIMAL', description: 'Minimal system', active: false, instanceRestrictions: [], systemType: '', configuration: { systemId: 'MIN', systemNumber: '99', clientNumber: '001', language: 'EN', applicationServerHostname: 'minimal.example.com', sapRouterString: '', sncActive: false, sncPartner: '', sncSsoMode: false, sncQualityOfProtection: 3 }, tags: [], assignedProjects: { projectsBefore: [], projectsAfterChange: [] }, permission: { deletable: true, editable: true } }; mockClient.getSapSystem.mockResolvedValue(minimalSystem); const result = await detailsHandler( new URL('simplifier://sap-system/MINIMAL'), { sapSystemName: 'MINIMAL' } ); expect(result).toMatchObject({ name: 'MINIMAL', active: false, instanceRestrictions: [], systemType: '', configuration: expect.objectContaining({ systemId: 'MIN', sapRouterString: '', sncActive: false }), tags: [] }); }); }); describe('Error Handling', () => { it('should propagate errors from listSapSystems', async () => { registerSapSystemResources(mockServer, mockClient); const listResourceCall = mockServer.resource.mock.calls.find( call => call[0] === 'sap-systems-list' ); const listHandler = listResourceCall![3] as Function; const testError = new Error('API Error'); mockClient.listSapSystems.mockRejectedValue(testError); mockWrapResourceResult.mockImplementation(async (_uri: any, callback: any) => { return callback(); }); await expect( listHandler(new URL('simplifier://sap-systems')) ).rejects.toThrow('API Error'); }); it('should propagate errors from getSapSystem', async () => { registerSapSystemResources(mockServer, mockClient); const detailsResourceCall = mockServer.resource.mock.calls.find( call => call[0] === 'sap-system-details' ); const detailsHandler = detailsResourceCall![3] as Function; const testError = new Error('System not found'); mockClient.getSapSystem.mockRejectedValue(testError); mockWrapResourceResult.mockImplementation(async (_uri: any, callback: any) => { return callback(); }); await expect( detailsHandler( new URL('simplifier://sap-system/NONEXISTENT'), { sapSystemName: 'NONEXISTENT' } ) ).rejects.toThrow('System not found'); }); }); });

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/SimplifierIO/simplifier-mcp'

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