mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 06:20:04 +00:00
test(browser): 添加 Phase 6A 失败测试
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
68b56839db
commit
491e9db51e
@@ -1347,6 +1347,10 @@ describe('ccs-browser MCP server', () => {
|
|||||||
'browser_select_page',
|
'browser_select_page',
|
||||||
'browser_open_page',
|
'browser_open_page',
|
||||||
'browser_close_page',
|
'browser_close_page',
|
||||||
|
'browser_add_intercept_rule',
|
||||||
|
'browser_remove_intercept_rule',
|
||||||
|
'browser_list_intercept_rules',
|
||||||
|
'browser_list_requests',
|
||||||
'browser_take_screenshot',
|
'browser_take_screenshot',
|
||||||
'browser_wait_for',
|
'browser_wait_for',
|
||||||
'browser_eval',
|
'browser_eval',
|
||||||
@@ -1386,6 +1390,24 @@ describe('ccs-browser MCP server', () => {
|
|||||||
expect(closeTool?.inputSchema?.properties?.pageIndex).toMatchObject({ type: 'integer' });
|
expect(closeTool?.inputSchema?.properties?.pageIndex).toMatchObject({ type: 'integer' });
|
||||||
expect(closeTool?.inputSchema?.properties?.pageId).toMatchObject({ type: 'string' });
|
expect(closeTool?.inputSchema?.properties?.pageId).toMatchObject({ type: 'string' });
|
||||||
|
|
||||||
|
const addRuleTool = tools.find((tool) => tool.name === 'browser_add_intercept_rule');
|
||||||
|
expect(addRuleTool?.inputSchema?.properties?.pageIndex).toMatchObject({ type: 'integer' });
|
||||||
|
expect(addRuleTool?.inputSchema?.properties?.pageId).toMatchObject({ type: 'string' });
|
||||||
|
expect(addRuleTool?.inputSchema?.properties?.urlIncludes).toMatchObject({ type: 'string' });
|
||||||
|
expect(addRuleTool?.inputSchema?.properties?.method).toMatchObject({ type: 'string' });
|
||||||
|
expect(addRuleTool?.inputSchema?.properties?.action).toMatchObject({ type: 'string' });
|
||||||
|
|
||||||
|
const removeRuleTool = tools.find((tool) => tool.name === 'browser_remove_intercept_rule');
|
||||||
|
expect(removeRuleTool?.inputSchema?.properties?.ruleId).toMatchObject({ type: 'string' });
|
||||||
|
|
||||||
|
const listRulesTool = tools.find((tool) => tool.name === 'browser_list_intercept_rules');
|
||||||
|
expect(listRulesTool?.inputSchema).toMatchObject({ type: 'object' });
|
||||||
|
|
||||||
|
const listRequestsTool = tools.find((tool) => tool.name === 'browser_list_requests');
|
||||||
|
expect(listRequestsTool?.inputSchema?.properties?.pageIndex).toMatchObject({ type: 'integer' });
|
||||||
|
expect(listRequestsTool?.inputSchema?.properties?.pageId).toMatchObject({ type: 'string' });
|
||||||
|
expect(listRequestsTool?.inputSchema?.properties?.limit).toMatchObject({ type: 'integer' });
|
||||||
|
|
||||||
const queryTool = tools.find((tool) => tool.name === 'browser_query');
|
const queryTool = tools.find((tool) => tool.name === 'browser_query');
|
||||||
expect(queryTool?.inputSchema?.properties?.fields).toMatchObject({
|
expect(queryTool?.inputSchema?.properties?.fields).toMatchObject({
|
||||||
type: 'array',
|
type: 'array',
|
||||||
@@ -1653,6 +1675,228 @@ describe('ccs-browser MCP server', () => {
|
|||||||
expect(listText).not.toContain('https://example.com/new');
|
expect(listText).not.toContain('https://example.com/new');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('adds an interception rule and lists it by bound pageId', async () => {
|
||||||
|
const responses = await runMcpRequests(
|
||||||
|
[
|
||||||
|
{ id: 'page-1', title: 'Home', currentUrl: 'https://example.com/' },
|
||||||
|
{ id: 'page-2', title: 'Docs', currentUrl: 'https://example.com/docs' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 901,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_select_page',
|
||||||
|
arguments: { pageIndex: 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 902,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_add_intercept_rule',
|
||||||
|
arguments: { urlIncludes: '/api', method: 'GET', action: 'continue' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 903,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_list_intercept_rules',
|
||||||
|
arguments: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const listText = getResponseText(responses.find((message) => message.id === 903));
|
||||||
|
expect(listText).toContain('pageId: page-2');
|
||||||
|
expect(listText).toContain('urlIncludes: /api');
|
||||||
|
expect(listText).toContain('method: GET');
|
||||||
|
expect(listText).toContain('action: continue');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps an existing rule bound to the original page after selected page changes', async () => {
|
||||||
|
const responses = await runMcpRequests(
|
||||||
|
[
|
||||||
|
{ id: 'page-1', title: 'Home', currentUrl: 'https://example.com/' },
|
||||||
|
{ id: 'page-2', title: 'Docs', currentUrl: 'https://example.com/docs' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 911,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_select_page', arguments: { pageIndex: 0 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 912,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_add_intercept_rule',
|
||||||
|
arguments: { urlIncludes: '/api', method: 'POST', action: 'fail' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 913,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_select_page', arguments: { pageIndex: 1 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 914,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_list_intercept_rules', arguments: {} },
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const listText = getResponseText(responses.find((message) => message.id === 914));
|
||||||
|
expect(listText).toContain('pageId: page-1');
|
||||||
|
expect(listText).toContain('method: POST');
|
||||||
|
expect(listText).toContain('action: fail');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes an interception rule by ruleId', async () => {
|
||||||
|
const responses = await runMcpRequests(
|
||||||
|
[{ id: 'page-1', title: 'Home', currentUrl: 'https://example.com/' }],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 921,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_add_intercept_rule',
|
||||||
|
arguments: { urlIncludes: '/api', method: 'GET', action: 'continue' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 922,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_remove_intercept_rule',
|
||||||
|
arguments: { ruleId: 'rule-1' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 923,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_list_intercept_rules', arguments: {} },
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeText = getResponseText(responses.find((message) => message.id === 922));
|
||||||
|
expect(removeText).toContain('ruleId: rule-1');
|
||||||
|
expect(removeText).toContain('status: removed');
|
||||||
|
|
||||||
|
const listText = getResponseText(responses.find((message) => message.id === 923));
|
||||||
|
expect(listText).toBe('status: empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('records recent requests with matched rule action summaries', async () => {
|
||||||
|
const responses = await runMcpRequests(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: 'page-1',
|
||||||
|
title: 'Home',
|
||||||
|
currentUrl: 'https://example.com/',
|
||||||
|
intercept: {
|
||||||
|
pausedRequests: [
|
||||||
|
{
|
||||||
|
requestId: 'req-1',
|
||||||
|
url: 'https://example.com/api/users',
|
||||||
|
method: 'GET',
|
||||||
|
resourceType: 'XHR',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requestId: 'req-2',
|
||||||
|
url: 'https://example.com/assets/app.js',
|
||||||
|
method: 'GET',
|
||||||
|
resourceType: 'Script',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 931,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_add_intercept_rule',
|
||||||
|
arguments: { urlIncludes: '/api', method: 'GET', action: 'fail' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 932,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_list_requests', arguments: {} },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
responseTimeoutMs: 12000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const listText = getResponseText(responses.find((message) => message.id === 932));
|
||||||
|
expect(listText).toContain('requestId: req-1');
|
||||||
|
expect(listText).toContain('matchedRuleId: rule-1');
|
||||||
|
expect(listText).toContain('action: fail');
|
||||||
|
expect(listText).toContain('requestId: req-2');
|
||||||
|
expect(listText).toContain('action: continue');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes rules bound to a page after that page is closed', async () => {
|
||||||
|
const responses = await runMcpRequests(
|
||||||
|
[
|
||||||
|
{ id: 'page-1', title: 'Home', currentUrl: 'https://example.com/' },
|
||||||
|
{ id: 'page-2', title: 'Docs', currentUrl: 'https://example.com/docs' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 941,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_select_page', arguments: { pageIndex: 1 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 942,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'browser_add_intercept_rule',
|
||||||
|
arguments: { urlIncludes: '/api', method: 'GET', action: 'continue' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 943,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_close_page', arguments: { pageId: 'page-2' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 944,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: { name: 'browser_list_intercept_rules', arguments: {} },
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const listText = getResponseText(responses.find((message) => message.id === 944));
|
||||||
|
expect(listText).not.toContain('pageId: page-2');
|
||||||
|
});
|
||||||
|
|
||||||
it('works from an installed copy when global WebSocket is unavailable and NODE_PATH supplies package dependencies', async () => {
|
it('works from an installed copy when global WebSocket is unavailable and NODE_PATH supplies package dependencies', async () => {
|
||||||
const installDir = mkdtempSync(join(tmpdir(), 'ccs-browser-installed-copy-'));
|
const installDir = mkdtempSync(join(tmpdir(), 'ccs-browser-installed-copy-'));
|
||||||
const installedServerPath = join(installDir, 'ccs-browser-server.cjs');
|
const installedServerPath = join(installDir, 'ccs-browser-server.cjs');
|
||||||
|
|||||||
Reference in New Issue
Block a user