|
1 | | -import { describe, it, expect } from 'vitest'; |
| 1 | +import { describe, it, expect, beforeEach } from 'vitest'; |
2 | 2 | import { z } from 'zod'; |
3 | 3 | import { createMockExecutor } from '../../../../test-utils/mock-executors.ts'; |
| 4 | +import { sessionStore } from '../../../../utils/session-store.ts'; |
4 | 5 | import tool, { buildRunMacOSLogic } from '../build_run_macos.ts'; |
5 | 6 |
|
6 | 7 | describe('build_run_macos', () => { |
| 8 | + beforeEach(() => { |
| 9 | + sessionStore.clear(); |
| 10 | + }); |
| 11 | + |
7 | 12 | describe('Export Field Validation (Literal)', () => { |
8 | 13 | it('should export the correct name', () => { |
9 | 14 | expect(tool.name).toBe('build_run_macos'); |
10 | 15 | }); |
11 | 16 |
|
12 | 17 | it('should export the correct description', () => { |
13 | | - expect(tool.description).toBe( |
14 | | - "Builds and runs a macOS app from a project or workspace in one step. Provide exactly one of projectPath or workspacePath. Example: build_run_macos({ projectPath: '/path/to/MyProject.xcodeproj', scheme: 'MyScheme' })", |
15 | | - ); |
| 18 | + expect(tool.description).toBe('Builds and runs a macOS app.'); |
16 | 19 | }); |
17 | 20 |
|
18 | 21 | it('should export a handler function', () => { |
19 | 22 | expect(typeof tool.handler).toBe('function'); |
20 | 23 | }); |
21 | 24 |
|
22 | | - it('should validate schema with valid project inputs', () => { |
23 | | - const validInput = { |
24 | | - projectPath: '/path/to/project.xcodeproj', |
25 | | - scheme: 'MyApp', |
26 | | - configuration: 'Debug', |
27 | | - derivedDataPath: '/path/to/derived', |
28 | | - arch: 'arm64', |
29 | | - extraArgs: ['--verbose'], |
30 | | - preferXcodebuild: true, |
31 | | - }; |
| 25 | + it('should expose only non-session fields in schema', () => { |
32 | 26 | const schema = z.object(tool.schema); |
33 | | - expect(schema.safeParse(validInput).success).toBe(true); |
34 | | - }); |
35 | 27 |
|
36 | | - it('should validate schema with valid workspace inputs', () => { |
37 | | - const validInput = { |
38 | | - workspacePath: '/path/to/workspace.xcworkspace', |
39 | | - scheme: 'MyApp', |
40 | | - configuration: 'Debug', |
41 | | - derivedDataPath: '/path/to/derived', |
42 | | - arch: 'arm64', |
43 | | - extraArgs: ['--verbose'], |
44 | | - preferXcodebuild: true, |
45 | | - }; |
46 | | - const schema = z.object(tool.schema); |
47 | | - expect(schema.safeParse(validInput).success).toBe(true); |
| 28 | + expect(schema.safeParse({}).success).toBe(true); |
| 29 | + expect( |
| 30 | + schema.safeParse({ |
| 31 | + derivedDataPath: '/tmp/derived', |
| 32 | + extraArgs: ['--verbose'], |
| 33 | + preferXcodebuild: true, |
| 34 | + }).success, |
| 35 | + ).toBe(true); |
| 36 | + |
| 37 | + expect(schema.safeParse({ derivedDataPath: 1 }).success).toBe(false); |
| 38 | + expect(schema.safeParse({ extraArgs: ['--ok', 2] }).success).toBe(false); |
| 39 | + expect(schema.safeParse({ preferXcodebuild: 'yes' }).success).toBe(false); |
| 40 | + |
| 41 | + const schemaKeys = Object.keys(tool.schema).sort(); |
| 42 | + expect(schemaKeys).toEqual(['derivedDataPath', 'extraArgs', 'preferXcodebuild'].sort()); |
48 | 43 | }); |
| 44 | + }); |
49 | 45 |
|
50 | | - it('should validate schema with minimal valid project inputs', () => { |
51 | | - const validInput = { |
52 | | - projectPath: '/path/to/project.xcodeproj', |
53 | | - scheme: 'MyApp', |
54 | | - }; |
55 | | - const schema = z.object(tool.schema); |
56 | | - expect(schema.safeParse(validInput).success).toBe(true); |
57 | | - }); |
| 46 | + describe('Handler Requirements', () => { |
| 47 | + it('should require scheme before executing', async () => { |
| 48 | + const result = await tool.handler({}); |
58 | 49 |
|
59 | | - it('should validate schema with minimal valid workspace inputs', () => { |
60 | | - const validInput = { |
61 | | - workspacePath: '/path/to/workspace.xcworkspace', |
62 | | - scheme: 'MyApp', |
63 | | - }; |
64 | | - const schema = z.object(tool.schema); |
65 | | - expect(schema.safeParse(validInput).success).toBe(true); |
| 50 | + expect(result.isError).toBe(true); |
| 51 | + expect(result.content[0].text).toContain('scheme is required'); |
66 | 52 | }); |
67 | 53 |
|
68 | | - it('should reject inputs with both projectPath and workspacePath', () => { |
69 | | - const invalidInput = { |
70 | | - projectPath: '/path/to/project.xcodeproj', |
71 | | - workspacePath: '/path/to/workspace.xcworkspace', |
72 | | - scheme: 'MyApp', |
73 | | - }; |
74 | | - const schema = z.object(tool.schema); |
75 | | - expect(schema.safeParse(invalidInput).success).toBe(true); // Base schema passes, but runtime validation should fail |
76 | | - }); |
| 54 | + it('should require project or workspace once scheme is set', async () => { |
| 55 | + sessionStore.setDefaults({ scheme: 'MyApp' }); |
77 | 56 |
|
78 | | - it('should reject inputs with neither projectPath nor workspacePath', () => { |
79 | | - const invalidInput = { |
80 | | - scheme: 'MyApp', |
81 | | - }; |
82 | | - const schema = z.object(tool.schema); |
83 | | - expect(schema.safeParse(invalidInput).success).toBe(true); // Base schema passes, but runtime validation should fail |
84 | | - }); |
| 57 | + const result = await tool.handler({}); |
85 | 58 |
|
86 | | - it('should reject invalid projectPath', () => { |
87 | | - const invalidInput = { |
88 | | - projectPath: 123, |
89 | | - scheme: 'MyApp', |
90 | | - }; |
91 | | - const schema = z.object(tool.schema); |
92 | | - expect(schema.safeParse(invalidInput).success).toBe(false); |
| 59 | + expect(result.isError).toBe(true); |
| 60 | + expect(result.content[0].text).toContain('Provide a project or workspace'); |
93 | 61 | }); |
94 | 62 |
|
95 | | - it('should reject invalid scheme', () => { |
96 | | - const invalidInput = { |
97 | | - projectPath: '/path/to/project.xcodeproj', |
98 | | - scheme: 123, |
99 | | - }; |
100 | | - const schema = z.object(tool.schema); |
101 | | - expect(schema.safeParse(invalidInput).success).toBe(false); |
102 | | - }); |
| 63 | + it('should fail when both project and workspace provided explicitly', async () => { |
| 64 | + sessionStore.setDefaults({ scheme: 'MyApp' }); |
103 | 65 |
|
104 | | - it('should reject invalid arch', () => { |
105 | | - const invalidInput = { |
| 66 | + const result = await tool.handler({ |
106 | 67 | projectPath: '/path/to/project.xcodeproj', |
107 | | - scheme: 'MyApp', |
108 | | - arch: 'invalid', |
109 | | - }; |
110 | | - const schema = z.object(tool.schema); |
111 | | - expect(schema.safeParse(invalidInput).success).toBe(false); |
| 68 | + workspacePath: '/path/to/workspace.xcworkspace', |
| 69 | + }); |
| 70 | + |
| 71 | + expect(result.isError).toBe(true); |
| 72 | + expect(result.content[0].text).toContain('Mutually exclusive parameters provided'); |
112 | 73 | }); |
113 | 74 | }); |
114 | 75 |
|
|
0 commit comments