-
-
Notifications
You must be signed in to change notification settings - Fork 194
ci: make MCP registry publish optional; fix video background; pin AXe 1.1.1 #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 1.1.1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -107,3 +107,4 @@ bundled/ | |
| /.mcpregistry_github_token | ||
| /.mcpregistry_registry_token | ||
| /key.pem | ||
| .mcpli | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,189 @@ | ||||||||
| import { describe, it, expect, vi, afterEach } from 'vitest'; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Violation of Vitest mocking constraint in coding guidelines. The coding guidelines explicitly state that files matching Apply this diff to remove the Vitest mocking import: -import { describe, it, expect, vi, afterEach } from 'vitest';
+import { describe, it, expect, afterEach } from 'vitest';📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
| import { z } from 'zod'; | ||||||||
|
|
||||||||
| // Import the tool and logic | ||||||||
| import tool, { record_sim_videoLogic } from '../record_sim_video.ts'; | ||||||||
| import { createMockFileSystemExecutor } from '../../../../test-utils/mock-executors.ts'; | ||||||||
|
|
||||||||
| const DUMMY_EXECUTOR: any = (async () => ({ success: true })) as any; // CommandExecutor stub | ||||||||
| const VALID_UUID = '00000000-0000-0000-0000-000000000000'; | ||||||||
|
|
||||||||
| afterEach(() => { | ||||||||
| vi.restoreAllMocks(); | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Unnecessary Mock Restoration in Dependency Injection TestThe test uses |
||||||||
| }); | ||||||||
|
Comment on lines
+11
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove mocking-related cleanup since no mocking is used. With the removal of Apply this diff to remove the unnecessary cleanup: -afterEach(() => {
- vi.restoreAllMocks();
-});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
|
|
||||||||
| describe('record_sim_video tool - validation', () => { | ||||||||
| it('errors when start and stop are both true (mutually exclusive)', async () => { | ||||||||
| const res = await tool.handler({ | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| start: true, | ||||||||
| stop: true, | ||||||||
| } as any); | ||||||||
|
|
||||||||
| expect(res.isError).toBe(true); | ||||||||
| const text = (res.content?.[0] as any)?.text ?? ''; | ||||||||
| expect(text.toLowerCase()).toContain('mutually exclusive'); | ||||||||
| }); | ||||||||
|
|
||||||||
| it('errors when stop=true but outputFile is missing', async () => { | ||||||||
| const res = await tool.handler({ | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| stop: true, | ||||||||
| } as any); | ||||||||
|
|
||||||||
| expect(res.isError).toBe(true); | ||||||||
| const text = (res.content?.[0] as any)?.text ?? ''; | ||||||||
| expect(text.toLowerCase()).toContain('outputfile is required'); | ||||||||
| }); | ||||||||
| }); | ||||||||
|
|
||||||||
| describe('record_sim_video logic - start behavior', () => { | ||||||||
| it('starts with default fps (30) and warns when outputFile is provided on start (ignored)', async () => { | ||||||||
| const video: any = { | ||||||||
| startSimulatorVideoCapture: async () => ({ | ||||||||
| started: true, | ||||||||
| sessionId: 'sess-123', | ||||||||
| }), | ||||||||
| stopSimulatorVideoCapture: async () => ({ | ||||||||
| stopped: false, | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| // DI for AXe helpers: available and version OK | ||||||||
| const axe = { | ||||||||
| areAxeToolsAvailable: () => true, | ||||||||
| isAxeAtLeastVersion: async () => true, | ||||||||
| createAxeNotAvailableResponse: () => ({ | ||||||||
| content: [{ type: 'text', text: 'AXe not available' }], | ||||||||
| isError: true, | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| const fs = createMockFileSystemExecutor(); | ||||||||
|
|
||||||||
| const res = await record_sim_videoLogic( | ||||||||
| { | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| start: true, | ||||||||
| // fps omitted to hit default 30 | ||||||||
| outputFile: '/tmp/ignored.mp4', // should be ignored with a note | ||||||||
| } as any, | ||||||||
| DUMMY_EXECUTOR, | ||||||||
| axe, | ||||||||
| video, | ||||||||
| fs, | ||||||||
| ); | ||||||||
|
|
||||||||
| expect(res.isError).toBe(false); | ||||||||
| const texts = (res.content ?? []).map((c: any) => c.text).join('\n'); | ||||||||
|
|
||||||||
| expect(texts).toContain('🎥'); | ||||||||
| expect(texts).toMatch(/30\s*fps/i); | ||||||||
| expect(texts.toLowerCase()).toContain('outputfile is ignored'); | ||||||||
| expect(texts).toContain('Next Steps'); | ||||||||
| expect(texts).toContain('stop: true'); | ||||||||
| expect(texts).toContain('outputFile'); | ||||||||
| }); | ||||||||
| }); | ||||||||
|
|
||||||||
| describe('record_sim_video logic - end-to-end stop with rename', () => { | ||||||||
| it('stops, parses stdout path, and renames to outputFile', async () => { | ||||||||
| const video: any = { | ||||||||
| startSimulatorVideoCapture: async () => ({ | ||||||||
| started: true, | ||||||||
| sessionId: 'sess-abc', | ||||||||
| }), | ||||||||
| stopSimulatorVideoCapture: async () => ({ | ||||||||
| stopped: true, | ||||||||
| parsedPath: '/tmp/recorded.mp4', | ||||||||
| stdout: 'Saved to /tmp/recorded.mp4', | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| const fs = createMockFileSystemExecutor(); | ||||||||
|
|
||||||||
| const axe = { | ||||||||
| areAxeToolsAvailable: () => true, | ||||||||
| isAxeAtLeastVersion: async () => true, | ||||||||
| createAxeNotAvailableResponse: () => ({ | ||||||||
| content: [{ type: 'text', text: 'AXe not available' }], | ||||||||
| isError: true, | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| // Start (not strictly required for stop path, but included to mimic flow) | ||||||||
| const startRes = await record_sim_videoLogic( | ||||||||
| { | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| start: true, | ||||||||
| } as any, | ||||||||
| DUMMY_EXECUTOR, | ||||||||
| axe, | ||||||||
| video, | ||||||||
| fs, | ||||||||
| ); | ||||||||
| expect(startRes.isError).toBe(false); | ||||||||
|
|
||||||||
| // Stop and rename | ||||||||
| const outputFile = '/var/videos/final.mp4'; | ||||||||
| const stopRes = await record_sim_videoLogic( | ||||||||
| { | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| stop: true, | ||||||||
| outputFile, | ||||||||
| } as any, | ||||||||
| DUMMY_EXECUTOR, | ||||||||
| axe, | ||||||||
| video, | ||||||||
| fs, | ||||||||
| ); | ||||||||
|
|
||||||||
| expect(stopRes.isError).toBe(false); | ||||||||
| const texts = (stopRes.content ?? []).map((c: any) => c.text).join('\n'); | ||||||||
| expect(texts).toContain('Original file: /tmp/recorded.mp4'); | ||||||||
| expect(texts).toContain(`Saved to: ${outputFile}`); | ||||||||
|
|
||||||||
| // _meta should include final saved path | ||||||||
| expect((stopRes as any)._meta?.outputFile).toBe(outputFile); | ||||||||
| }); | ||||||||
| }); | ||||||||
|
|
||||||||
| describe('record_sim_video logic - version gate', () => { | ||||||||
| it('errors when AXe version is below 1.1.0', async () => { | ||||||||
| const axe = { | ||||||||
| areAxeToolsAvailable: () => true, | ||||||||
| isAxeAtLeastVersion: async () => false, | ||||||||
| createAxeNotAvailableResponse: () => ({ | ||||||||
| content: [{ type: 'text', text: 'AXe not available' }], | ||||||||
| isError: true, | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| const video: any = { | ||||||||
| startSimulatorVideoCapture: async () => ({ | ||||||||
| started: true, | ||||||||
| sessionId: 'sess-xyz', | ||||||||
| }), | ||||||||
| stopSimulatorVideoCapture: async () => ({ | ||||||||
| stopped: true, | ||||||||
| }), | ||||||||
| }; | ||||||||
|
|
||||||||
| const fs = createMockFileSystemExecutor(); | ||||||||
|
|
||||||||
| const res = await record_sim_videoLogic( | ||||||||
| { | ||||||||
| simulatorUuid: VALID_UUID, | ||||||||
| start: true, | ||||||||
| } as any, | ||||||||
| DUMMY_EXECUTOR, | ||||||||
| axe, | ||||||||
| video, | ||||||||
| fs, | ||||||||
| ); | ||||||||
|
|
||||||||
| expect(res.isError).toBe(true); | ||||||||
| const text = (res.content?.[0] as any)?.text ?? ''; | ||||||||
| expect(text).toContain('AXe v1.1.0'); | ||||||||
| }); | ||||||||
| }); | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
find expression may select non-directories; group predicates
Without grouping,
-name "*axe*"can match files of any type. Group and constrain both to directories.📝 Committable suggestion
🤖 Prompt for AI Agents