114 lines
3.3 KiB
TypeScript
114 lines
3.3 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mocks = vi.hoisted(() => {
|
|
const state = {
|
|
currentUrl: 'about:blank',
|
|
};
|
|
|
|
const page = {
|
|
url: vi.fn(() => state.currentUrl),
|
|
goto: vi.fn(async (url: string) => {
|
|
state.currentUrl = url;
|
|
}),
|
|
bringToFront: vi.fn(async () => {}),
|
|
title: vi.fn(async () => '百度一下,你就知道'),
|
|
};
|
|
|
|
const context = {
|
|
pages: vi.fn(() => [page]),
|
|
newPage: vi.fn(async () => page),
|
|
};
|
|
|
|
const browser = {
|
|
contexts: vi.fn(() => [context]),
|
|
disconnect: vi.fn(async () => {}),
|
|
close: vi.fn(async () => {}),
|
|
};
|
|
|
|
return {
|
|
state,
|
|
page,
|
|
context,
|
|
browser,
|
|
launchLocalChrome: vi.fn(async () => {}),
|
|
isChromeRunning: vi.fn(async () => true),
|
|
connectOverCDP: vi.fn(async () => browser),
|
|
logger: {
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock('@electron/utils/chrome/launchLocalChrome', () => ({
|
|
launchLocalChrome: mocks.launchLocalChrome,
|
|
}));
|
|
|
|
vi.mock('@electron/utils/chrome/isChromeRunning', () => ({
|
|
isChromeRunning: mocks.isChromeRunning,
|
|
}));
|
|
|
|
vi.mock('@electron/service/logger', () => ({
|
|
default: mocks.logger,
|
|
}));
|
|
|
|
vi.mock('playwright', () => ({
|
|
chromium: {
|
|
connectOverCDP: mocks.connectOverCDP,
|
|
},
|
|
}));
|
|
|
|
describe('browser open service', () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.clearAllMocks();
|
|
mocks.state.currentUrl = 'about:blank';
|
|
mocks.page.url.mockImplementation(() => mocks.state.currentUrl);
|
|
mocks.page.goto.mockImplementation(async (url: string) => {
|
|
mocks.state.currentUrl = url;
|
|
});
|
|
});
|
|
|
|
it('extracts an explicit open-url intent and normalizes the URL', async () => {
|
|
const { extractBrowserOpenIntent } = await import('../electron/service/browser-open-service');
|
|
|
|
expect(extractBrowserOpenIntent('打开 http://www.baidu.com。')).toEqual({
|
|
url: 'http://www.baidu.com/',
|
|
});
|
|
expect(extractBrowserOpenIntent('请帮我分析一下 http://www.baidu.com')).toBeNull();
|
|
expect(extractBrowserOpenIntent('打开 javascript:alert(1)')).toBeNull();
|
|
});
|
|
|
|
it('launches chrome via cdp and opens the requested page', async () => {
|
|
const { openUrlInBrowser } = await import('../electron/service/browser-open-service');
|
|
|
|
const result = await openUrlInBrowser('http://www.baidu.com');
|
|
|
|
expect(mocks.launchLocalChrome).toHaveBeenCalledTimes(1);
|
|
expect(mocks.connectOverCDP).toHaveBeenCalledWith('http://127.0.0.1:9222');
|
|
expect(mocks.page.bringToFront).toHaveBeenCalledTimes(1);
|
|
expect(mocks.page.goto).toHaveBeenCalledWith('http://www.baidu.com/', expect.objectContaining({
|
|
waitUntil: 'domcontentloaded',
|
|
timeout: 15000,
|
|
}));
|
|
expect(mocks.browser.disconnect).toHaveBeenCalledTimes(1);
|
|
expect(result).toEqual({
|
|
url: 'http://www.baidu.com/',
|
|
pageUrl: 'http://www.baidu.com/',
|
|
title: '百度一下,你就知道',
|
|
});
|
|
});
|
|
|
|
it('wraps cdp connection errors with a clearer message', async () => {
|
|
mocks.connectOverCDP.mockRejectedValueOnce(new Error('connect ECONNREFUSED 127.0.0.1:9222'));
|
|
|
|
const { openUrlInBrowser } = await import('../electron/service/browser-open-service');
|
|
|
|
await expect(openUrlInBrowser('http://www.baidu.com')).rejects.toThrow(
|
|
'Chrome 已启动但远程调试端口 9222 不可用',
|
|
);
|
|
});
|
|
});
|