mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
New browser launcher for MCP OAuth. (#5261)
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import * as http from 'node:http';
|
||||
import * as crypto from 'node:crypto';
|
||||
import open from 'open';
|
||||
import {
|
||||
MCPOAuthProvider,
|
||||
MCPOAuthConfig,
|
||||
@@ -17,7 +16,10 @@ import {
|
||||
import { MCPOAuthTokenStorage, MCPOAuthToken } from './oauth-token-storage.js';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('open');
|
||||
const mockOpenBrowserSecurely = vi.hoisted(() => vi.fn());
|
||||
vi.mock('../utils/secure-browser-launcher.js', () => ({
|
||||
openBrowserSecurely: mockOpenBrowserSecurely,
|
||||
}));
|
||||
vi.mock('node:crypto');
|
||||
vi.mock('./oauth-token-storage.js');
|
||||
|
||||
@@ -64,6 +66,7 @@ describe('MCPOAuthProvider', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockOpenBrowserSecurely.mockClear();
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
@@ -145,7 +148,9 @@ describe('MCPOAuthProvider', () => {
|
||||
expiresAt: expect.any(Number),
|
||||
});
|
||||
|
||||
expect(open).toHaveBeenCalledWith(expect.stringContaining('authorize'));
|
||||
expect(mockOpenBrowserSecurely).toHaveBeenCalledWith(
|
||||
expect.stringContaining('authorize'),
|
||||
);
|
||||
expect(MCPOAuthTokenStorage.saveToken).toHaveBeenCalledWith(
|
||||
'test-server',
|
||||
expect.objectContaining({ accessToken: 'access_token_123' }),
|
||||
@@ -672,13 +677,10 @@ describe('MCPOAuthProvider', () => {
|
||||
describe('Authorization URL building', () => {
|
||||
it('should build correct authorization URL with all parameters', async () => {
|
||||
// Mock to capture the URL that would be opened
|
||||
let capturedUrl: string;
|
||||
vi.mocked(open).mockImplementation((url) => {
|
||||
let capturedUrl: string | undefined;
|
||||
mockOpenBrowserSecurely.mockImplementation((url: string) => {
|
||||
capturedUrl = url;
|
||||
// Return a minimal mock ChildProcess
|
||||
return Promise.resolve({
|
||||
pid: 1234,
|
||||
} as unknown as import('child_process').ChildProcess);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
let callbackHandler: unknown;
|
||||
@@ -711,6 +713,7 @@ describe('MCPOAuthProvider', () => {
|
||||
|
||||
await MCPOAuthProvider.authenticate('test-server', mockConfig);
|
||||
|
||||
expect(capturedUrl).toBeDefined();
|
||||
expect(capturedUrl!).toContain('response_type=code');
|
||||
expect(capturedUrl!).toContain('client_id=test-client-id');
|
||||
expect(capturedUrl!).toContain('code_challenge=code_challenge_mock');
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import * as http from 'node:http';
|
||||
import * as crypto from 'node:crypto';
|
||||
import { URL } from 'node:url';
|
||||
import open from 'open';
|
||||
import { openBrowserSecurely } from '../utils/secure-browser-launcher.js';
|
||||
import { MCPOAuthToken, MCPOAuthTokenStorage } from './oauth-token-storage.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import { OAuthUtils } from './oauth-utils.js';
|
||||
@@ -593,9 +593,9 @@ export class MCPOAuthProvider {
|
||||
// Start callback server
|
||||
const callbackPromise = this.startCallbackServer(pkceParams.state);
|
||||
|
||||
// Open browser
|
||||
// Open browser securely
|
||||
try {
|
||||
await open(authUrl);
|
||||
await openBrowserSecurely(authUrl);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to open browser automatically:',
|
||||
|
||||
Reference in New Issue
Block a user