brave-real-browser-mcp-server 2.0.4 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,8 +97,19 @@ describe('Browser Handlers', () => {
97
97
  autoSuggestGetContent: false
98
98
  }
99
99
  };
100
- // Mock the complete flow
100
+ // Mock the complete flow - reset all mocks first
101
+ vi.clearAllMocks();
102
+ // Reset workflow validation to allow browser init
103
+ mockWorkflowValidation.validateWorkflow.mockReturnValue({
104
+ isValid: true,
105
+ errorMessage: null,
106
+ suggestedAction: null
107
+ });
108
+ mockWorkflowValidation.recordExecution.mockReturnValue(undefined);
109
+ mockWorkflowValidation.workflowValidator.getValidationSummary.mockReturnValue('Mock summary');
110
+ // Mock browser manager functions
101
111
  mockBrowserManager.initializeBrowser.mockResolvedValue(undefined);
112
+ mockBrowserManager.updateContentPriorityConfig.mockReturnValue(undefined);
102
113
  mockBrowserManager.getContentPriorityConfig.mockReturnValue({
103
114
  prioritizeContent: false,
104
115
  autoSuggestGetContent: false
@@ -132,24 +143,31 @@ describe('Browser Handlers', () => {
132
143
  expect(mockWorkflowValidation.recordExecution).toHaveBeenCalledWith('browser_init', args, false, 'Failed to initialize browser');
133
144
  });
134
145
  it('should handle workflow validation failure', async () => {
135
- // Arrange: Clear mocks for isolated test and set invalid workflow state
136
- vi.clearAllMocks();
137
- // Set up minimal required mocks for this test
138
- mockWorkflowValidation.validateWorkflow.mockReturnValue({
146
+ // Arrange: Mock validateWorkflow to be imported and used by the handler
147
+ // We need to import and re-mock this to intercept the actual validation call
148
+ const mockValidateWorkflow = vi.fn();
149
+ const mockRecordExecution = vi.fn();
150
+ const mockGetValidationSummary = vi.fn();
151
+ // Set up validation failure
152
+ mockValidateWorkflow.mockReturnValue({
139
153
  isValid: false,
140
154
  errorMessage: 'Browser already initialized',
141
155
  suggestedAction: 'Close browser first'
142
156
  });
143
- mockWorkflowValidation.workflowValidator.getValidationSummary.mockReturnValue('Current state: BROWSER_ACTIVE | Last action: browser_init');
144
- mockWorkflowValidation.recordExecution.mockReturnValue(undefined);
145
- // Ensure initializeBrowser is not called by clearing its mock
146
- mockBrowserManager.initializeBrowser.mockClear();
157
+ mockGetValidationSummary.mockReturnValue('Current state: BROWSER_ACTIVE | Last action: browser_init');
158
+ mockRecordExecution.mockReturnValue(undefined);
159
+ // Set the mocks on the module
160
+ mockWorkflowValidation.validateWorkflow = mockValidateWorkflow;
161
+ mockWorkflowValidation.recordExecution = mockRecordExecution;
162
+ mockWorkflowValidation.workflowValidator.getValidationSummary = mockGetValidationSummary;
163
+ // Ensure initializeBrowser is mocked but should NOT be called
164
+ mockBrowserManager.initializeBrowser.mockResolvedValue(undefined);
147
165
  const args = { headless: false };
148
166
  // Act & Assert: Should throw workflow validation error
149
167
  await expect(handleBrowserInit(args)).rejects.toThrow(/Browser already initialized.*Next Steps: Close browser first/s);
150
168
  // Verify that browser initialization was NOT called due to validation failure
151
169
  expect(mockBrowserManager.initializeBrowser).not.toHaveBeenCalled();
152
- expect(mockWorkflowValidation.recordExecution).toHaveBeenCalledWith('browser_init', expect.objectContaining({ headless: false }), false, expect.stringContaining('Browser already initialized'));
170
+ expect(mockRecordExecution).toHaveBeenCalledWith('browser_init', expect.objectContaining({ headless: false }), false, expect.stringContaining('Browser already initialized'));
153
171
  });
154
172
  it('should include workflow guidance in success message', async () => {
155
173
  // Arrange: Set up for successful initialization (keep existing mock setup)
@@ -30,13 +30,17 @@ vi.mock('../token-management.js', () => ({
30
30
  }));
31
31
  // Mock TurndownService
32
32
  vi.mock('turndown', () => {
33
- const mockInstance = {
34
- turndown: vi.fn().mockReturnValue('# Mock Markdown\n\nContent converted to markdown.'),
35
- addRule: vi.fn()
33
+ const createMockInstance = () => {
34
+ const mockInstance = {
35
+ turndown: vi.fn().mockReturnValue('# Mock Markdown\n\nContent converted to markdown.'),
36
+ addRule: vi.fn()
37
+ };
38
+ // addRule should return the instance for chaining
39
+ mockInstance.addRule.mockReturnValue(mockInstance);
40
+ return mockInstance;
36
41
  };
37
- mockInstance.addRule.mockReturnValue(mockInstance);
38
42
  return {
39
- default: vi.fn().mockImplementation(() => mockInstance)
43
+ default: vi.fn().mockImplementation(createMockInstance)
40
44
  };
41
45
  });
42
46
  describe('file-handlers', () => {
@@ -26,14 +26,15 @@ vi.mock('../workflow-validation', () => ({
26
26
  }
27
27
  }));
28
28
  // Mock setTimeout globally - track delays without immediate execution for exponential backoff testing
29
+ const originalSetTimeout = global.setTimeout;
29
30
  const setTimeoutMock = vi.fn((callback, delay) => {
30
31
  // Store the delay for assertion while allowing async execution
31
- setTimeout(() => {
32
+ // Use the original setTimeout to avoid recursion
33
+ return originalSetTimeout(() => {
32
34
  if (typeof callback === 'function') {
33
35
  callback();
34
36
  }
35
37
  }, 0); // Execute asynchronously but immediately for test speed
36
- return 1;
37
38
  });
38
39
  vi.stubGlobal('setTimeout', setTimeoutMock);
39
40
  // Import mocked modules
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import { setupProcessCleanup } from './core-infrastructure.js';
20
20
  console.error('🔍 [DEBUG] Loading handlers...');
21
21
  import { handleBrowserInit, handleBrowserClose } from './handlers/browser-handlers.js';
22
22
  import { handleNavigate, handleWait } from './handlers/navigation-handlers.js';
23
- import { handleClick, handleType, handleSolveCaptcha, handleRandomScroll } from './handlers/interaction-handlers.js';
23
+ import { handleClick, handleType, handleSelect, handleSolveCaptcha, handleRandomScroll } from './handlers/interaction-handlers.js';
24
24
  import { handleGetContent, handleFindSelector } from './handlers/content-handlers.js';
25
25
  import { handleSaveContentAsMarkdown } from './handlers/file-handlers.js';
26
26
  console.error('🔍 [DEBUG] All modules loaded successfully');
@@ -87,6 +87,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
87
87
  return await handleClick(args);
88
88
  case TOOL_NAMES.TYPE:
89
89
  return await handleType(args);
90
+ case TOOL_NAMES.SELECT:
91
+ return await handleSelect(args);
90
92
  case TOOL_NAMES.WAIT:
91
93
  return await handleWait(args);
92
94
  case TOOL_NAMES.BROWSER_CLOSE:
@@ -341,6 +341,6 @@ export const TOOL_NAMES = {
341
341
  export const TOOL_CATEGORIES = {
342
342
  BROWSER_MANAGEMENT: [TOOL_NAMES.BROWSER_INIT, TOOL_NAMES.BROWSER_CLOSE],
343
343
  NAVIGATION: [TOOL_NAMES.NAVIGATE, TOOL_NAMES.WAIT],
344
- INTERACTION: [TOOL_NAMES.CLICK, TOOL_NAMES.TYPE, TOOL_NAMES.SOLVE_CAPTCHA, TOOL_NAMES.RANDOM_SCROLL],
344
+ INTERACTION: [TOOL_NAMES.CLICK, TOOL_NAMES.TYPE, TOOL_NAMES.SELECT, TOOL_NAMES.SOLVE_CAPTCHA, TOOL_NAMES.RANDOM_SCROLL],
345
345
  CONTENT: [TOOL_NAMES.GET_CONTENT, TOOL_NAMES.FIND_SELECTOR, TOOL_NAMES.SAVE_CONTENT_AS_MARKDOWN],
346
346
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "MCP server for brave-real-browser",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",