Skip to main content
Glama

MCP Xcode

by Stefan-Nitu
BuildXcodeController.e2e.test.ts8.53 kB
/** * E2E Test for BuildXcodeController * * Tests BEHAVIOR with REAL xcodebuild: * - Can the controller actually build real projects? * - Do the destination mappings produce valid xcodebuild commands that work? * - Does error handling work with real build failures? * * NO MOCKS - uses real xcodebuild with test projects * Direct controller calls - does NOT test through MCP protocol */ import { MCPController } from '../../../../presentation/interfaces/MCPController.js'; import { BuildXcodeControllerFactory } from '../../factories/BuildXcodeControllerFactory.js'; import { TestProjectManager } from '../../../../shared/tests/utils/TestProjectManager.js'; import * as fs from 'fs'; describe('BuildXcodeController E2E', () => { let controller: MCPController; let testManager: TestProjectManager; beforeAll(async () => { testManager = new TestProjectManager(); await testManager.setup(); }); afterAll(async () => { await testManager.cleanup(); }); beforeEach(() => { // Create controller with all real dependencies controller = BuildXcodeControllerFactory.create(); }); describe('build real Xcode projects', () => { it('should successfully build iOS test project', async () => { // This tests that: // 1. Destination 'iOSSimulator' produces a valid xcodebuild command // 2. The entire stack can handle real xcodebuild output // 3. Success is properly detected and reported const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'iOSSimulator' }); // Should report success expect(result).toMatchObject({ content: expect.arrayContaining([ expect.objectContaining({ type: 'text', text: expect.stringContaining('Build succeeded') }) ]) }); }); it('should successfully build macOS test project', async () => { // This tests macOS destination mapping works const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'macOS' }); expect(result).toMatchObject({ content: expect.arrayContaining([ expect.objectContaining({ type: 'text', text: expect.stringContaining('Build succeeded') }) ]) }); }); it('should build with Release configuration', async () => { // This tests configuration is properly passed through const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'iOSSimulator', configuration: 'Release' }); expect(result).toMatchObject({ content: expect.arrayContaining([ expect.objectContaining({ type: 'text', text: expect.stringContaining('Build succeeded') }) ]) }); // Should mention Release configuration expect(result.content[0].text).toContain('Release'); }); it('should handle custom derived data path', async () => { // This tests that derived data path is properly used const customPath = `/tmp/TestDerivedData_${Date.now()}`; const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'iOSSimulator', derivedDataPath: customPath }); expect(result.content[0].text).toContain('Build succeeded'); // Derived data should exist at custom path expect(fs.existsSync(customPath)).toBe(true); // Cleanup fs.rmSync(customPath, { recursive: true, force: true }); }); }); describe('handle real build failures', () => { it('should report error for non-existent scheme', async () => { // This tests real xcodebuild error handling const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'NonExistentScheme', destination: 'iOSSimulator' }); // Should report failure expect(result.content[0].text).toContain('Build failed'); // Should include the actual xcodebuild error about the missing scheme expect(result.content[0].text).toContain('does not contain a scheme named "NonExistentScheme"'); }); it('should handle invalid platform for project', async () => { // Try to build a macOS-only project for iOS (if we have one) // or iOS-only project for watchOS const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'watchOSSimulator' }); // Should handle the failure gracefully expect(result.content[0].text).toContain('Build failed'); }); }); describe('build for all supported platforms', () => { it('should attempt to build for tvOS simulator', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'tvOSSimulator' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention tvOS in the result expect(result.content[0].text.toLowerCase()).toContain('tvos'); }); it('should attempt to build for watchOS simulator', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'watchOSSimulator' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention watchOS in the result expect(result.content[0].text.toLowerCase()).toContain('watchos'); }); it('should attempt to build for visionOS simulator', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'visionOSSimulator' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention visionOS or xrOS (internal name) in the result expect(result.content[0].text.toLowerCase()).toMatch(/visionos|xros/); }); it('should build for iOS device', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'iOSDevice' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should show it's building for iOS platform expect(result.content[0].text).toContain('Platform: iOS'); }); it('should attempt to build for tvOS device', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'tvOSDevice' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention tvOS in the result expect(result.content[0].text.toLowerCase()).toContain('tvos'); }); it('should attempt to build for watchOS device', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'watchOSDevice' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention watchOS in the result expect(result.content[0].text.toLowerCase()).toContain('watchos'); }); it('should build for visionOS device', async () => { const result = await controller.execute({ projectPath: testManager.paths.xcodeProjectXCTestPath, scheme: 'TestProjectXCTest', destination: 'visionOSDevice' }); // Should complete without throwing expect(result.content[0].text).toBeDefined(); // Should mention visionOS or xrOS in the result expect(result.content[0].text.toLowerCase()).toMatch(/visionos|xros/); }); }); });

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/Stefan-Nitu/mcp-xcode'

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