mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-11-04 15:00:11 +00:00
feat: support page reload (#462)
- merges navigation tools into a single tool. - adds reload functionality. - in a follow-up we will add options to reload.
This commit is contained in:
1 parent
21af8daf04
commit
d177087981
4 files changed
+99
-79
No files matched your search
@@ -247,11 +247,10 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
|
||||
- [`hover`](docs/tool-reference.md#hover)
|
||||
- [`press_key`](docs/tool-reference.md#press_key)
|
||||
- [`upload_file`](docs/tool-reference.md#upload_file)
|
||||
- **Navigation automation** (7 tools)
|
||||
- **Navigation automation** (6 tools)
|
||||
- [`close_page`](docs/tool-reference.md#close_page)
|
||||
- [`list_pages`](docs/tool-reference.md#list_pages)
|
||||
- [`navigate_page`](docs/tool-reference.md#navigate_page)
|
||||
- [`navigate_page_history`](docs/tool-reference.md#navigate_page_history)
|
||||
- [`new_page`](docs/tool-reference.md#new_page)
|
||||
- [`select_page`](docs/tool-reference.md#select_page)
|
||||
- [`wait_for`](docs/tool-reference.md#wait_for)
|
||||
|
||||
+3
-14
@@ -11,11 +11,10 @@
|
||||
- [`hover`](#hover)
|
||||
- [`press_key`](#press_key)
|
||||
- [`upload_file`](#upload_file)
|
||||
- **[Navigation automation](#navigation-automation)** (7 tools)
|
||||
- **[Navigation automation](#navigation-automation)** (6 tools)
|
||||
- [`close_page`](#close_page)
|
||||
- [`list_pages`](#list_pages)
|
||||
- [`navigate_page`](#navigate_page)
|
||||
- [`navigate_page_history`](#navigate_page_history)
|
||||
- [`new_page`](#new_page)
|
||||
- [`select_page`](#select_page)
|
||||
- [`wait_for`](#wait_for)
|
||||
@@ -151,18 +150,8 @@
|
||||
**Parameters:**
|
||||
|
||||
- **timeout** (integer) _(optional)_: Maximum wait time in milliseconds. If set to 0, the default timeout will be used.
|
||||
- **url** (string) **(required)**: URL to navigate the page to
|
||||
|
||||
---
|
||||
|
||||
### `navigate_page_history`
|
||||
|
||||
**Description:** Navigates the currently selected page.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- **navigate** (enum: "back", "forward") **(required)**: Whether to navigate back or navigate forward in the selected pages history
|
||||
- **timeout** (integer) _(optional)_: Maximum wait time in milliseconds. If set to 0, the default timeout will be used.
|
||||
- **type** (enum: "url", "back", "forward", "reload") _(optional)_: Navigate the page by URL, back or forward in history, or reload.
|
||||
- **url** (string) _(optional)_: Target URL (only type=url)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+65
-37
@@ -105,35 +105,13 @@ export const navigatePage = defineTool({
|
||||
readOnlyHint: false,
|
||||
},
|
||||
schema: {
|
||||
url: zod.string().describe('URL to navigate the page to'),
|
||||
...timeoutSchema,
|
||||
},
|
||||
handler: async (request, response, context) => {
|
||||
const page = context.getSelectedPage();
|
||||
|
||||
await context.waitForEventsAfterAction(async () => {
|
||||
await page.goto(request.params.url, {
|
||||
timeout: request.params.timeout,
|
||||
});
|
||||
});
|
||||
|
||||
response.setIncludePages(true);
|
||||
},
|
||||
});
|
||||
|
||||
export const navigatePageHistory = defineTool({
|
||||
name: 'navigate_page_history',
|
||||
description: `Navigates the currently selected page.`,
|
||||
annotations: {
|
||||
category: ToolCategory.NAVIGATION,
|
||||
readOnlyHint: false,
|
||||
},
|
||||
schema: {
|
||||
navigate: zod
|
||||
.enum(['back', 'forward'])
|
||||
type: zod
|
||||
.enum(['url', 'back', 'forward', 'reload'])
|
||||
.optional()
|
||||
.describe(
|
||||
'Whether to navigate back or navigate forward in the selected pages history',
|
||||
'Navigate the page by URL, back or forward in history, or reload.',
|
||||
),
|
||||
url: zod.string().optional().describe('Target URL (only type=url)'),
|
||||
...timeoutSchema,
|
||||
},
|
||||
handler: async (request, response, context) => {
|
||||
@@ -142,18 +120,68 @@ export const navigatePageHistory = defineTool({
|
||||
timeout: request.params.timeout,
|
||||
};
|
||||
|
||||
try {
|
||||
if (request.params.navigate === 'back') {
|
||||
await page.goBack(options);
|
||||
} else {
|
||||
await page.goForward(options);
|
||||
}
|
||||
} catch (error) {
|
||||
response.appendResponseLine(
|
||||
`Unable to navigate ${request.params.navigate} in currently selected page. ${error.message}`,
|
||||
);
|
||||
if (!request.params.type && !request.params.url) {
|
||||
throw new Error('Either URL or a type is required.');
|
||||
}
|
||||
|
||||
if (!request.params.type) {
|
||||
request.params.type = 'url';
|
||||
}
|
||||
|
||||
await context.waitForEventsAfterAction(async () => {
|
||||
switch (request.params.type) {
|
||||
case 'url':
|
||||
if (!request.params.url) {
|
||||
throw new Error('A URL is required for navigation of type=url.');
|
||||
}
|
||||
try {
|
||||
await page.goto(request.params.url, options);
|
||||
response.appendResponseLine(
|
||||
`Successfully navigated to ${request.params.url}.`,
|
||||
);
|
||||
} catch (error) {
|
||||
response.appendResponseLine(
|
||||
`Unable to navigate in the selected page: ${error.message}.`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'back':
|
||||
try {
|
||||
await page.goBack(options);
|
||||
response.appendResponseLine(
|
||||
`Successfully navigated back to ${page.url()}.`,
|
||||
);
|
||||
} catch (error) {
|
||||
response.appendResponseLine(
|
||||
`Unable to navigate back in the selected page: ${error.message}.`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'forward':
|
||||
try {
|
||||
await page.goForward(options);
|
||||
response.appendResponseLine(
|
||||
`Successfully navigated forward to ${page.url()}.`,
|
||||
);
|
||||
} catch (error) {
|
||||
response.appendResponseLine(
|
||||
`Unable to navigate forward in the selected page: ${error.message}.`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'reload':
|
||||
try {
|
||||
await page.reload(options);
|
||||
response.appendResponseLine(`Successfully reloaded the page.`);
|
||||
} catch (error) {
|
||||
response.appendResponseLine(
|
||||
`Unable to reload the selected page: ${error.message}.`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
response.setIncludePages(true);
|
||||
},
|
||||
});
|
||||
|
||||
+30
-26
@@ -14,7 +14,6 @@ import {
|
||||
closePage,
|
||||
selectPage,
|
||||
navigatePage,
|
||||
navigatePageHistory,
|
||||
resizePage,
|
||||
handleDialog,
|
||||
} from '../../src/tools/pages.js';
|
||||
@@ -29,7 +28,7 @@ describe('pages', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_new_page', () => {
|
||||
describe('new_page', () => {
|
||||
it('create a page', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
assert.strictEqual(context.getSelectedPageIdx(), 0);
|
||||
@@ -43,7 +42,7 @@ describe('pages', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_close_page', () => {
|
||||
describe('close_page', () => {
|
||||
it('closes a page', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
const page = await context.newPage();
|
||||
@@ -67,7 +66,7 @@ describe('pages', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_select_page', () => {
|
||||
describe('select_page', () => {
|
||||
it('selects a page', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
await context.newPage();
|
||||
@@ -78,7 +77,7 @@ describe('pages', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_navigate_page', () => {
|
||||
describe('navigate_page', () => {
|
||||
it('navigates to correct page', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
await navigatePage.handler(
|
||||
@@ -118,17 +117,11 @@ describe('pages', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_navigate_page_history', () => {
|
||||
it('go back', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
const page = context.getSelectedPage();
|
||||
await page.goto('data:text/html,<div>Hello MCP</div>');
|
||||
await navigatePageHistory.handler(
|
||||
{params: {navigate: 'back'}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
await navigatePage.handler({params: {type: 'back'}}, response, context);
|
||||
|
||||
assert.equal(
|
||||
await page.evaluate(() => document.location.href),
|
||||
@@ -142,8 +135,8 @@ describe('pages', () => {
|
||||
const page = context.getSelectedPage();
|
||||
await page.goto('data:text/html,<div>Hello MCP</div>');
|
||||
await page.goBack();
|
||||
await navigatePageHistory.handler(
|
||||
{params: {navigate: 'forward'}},
|
||||
await navigatePage.handler(
|
||||
{params: {type: 'forward'}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
@@ -155,10 +148,27 @@ describe('pages', () => {
|
||||
assert.ok(response.includePages);
|
||||
});
|
||||
});
|
||||
it('reload', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
const page = context.getSelectedPage();
|
||||
await page.goto('data:text/html,<div>Hello MCP</div>');
|
||||
await navigatePage.handler(
|
||||
{params: {type: 'reload'}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await page.evaluate(() => document.location.href),
|
||||
'data:text/html,<div>Hello MCP</div>',
|
||||
);
|
||||
assert.ok(response.includePages);
|
||||
});
|
||||
});
|
||||
it('go forward with error', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
await navigatePageHistory.handler(
|
||||
{params: {navigate: 'forward'}},
|
||||
await navigatePage.handler(
|
||||
{params: {type: 'forward'}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
@@ -166,31 +176,25 @@ describe('pages', () => {
|
||||
assert.ok(
|
||||
response.responseLines
|
||||
.at(0)
|
||||
?.startsWith(
|
||||
'Unable to navigate forward in currently selected page.',
|
||||
),
|
||||
?.startsWith('Unable to navigate forward in the selected page:'),
|
||||
);
|
||||
assert.ok(response.includePages);
|
||||
});
|
||||
});
|
||||
it('go back with error', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
await navigatePageHistory.handler(
|
||||
{params: {navigate: 'back'}},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
await navigatePage.handler({params: {type: 'back'}}, response, context);
|
||||
|
||||
assert.ok(
|
||||
response.responseLines
|
||||
.at(0)
|
||||
?.startsWith('Unable to navigate back in currently selected page.'),
|
||||
?.startsWith('Unable to navigate back in the selected page:'),
|
||||
);
|
||||
assert.ok(response.includePages);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('browser_resize', () => {
|
||||
describe('resize', () => {
|
||||
it('create a page', async () => {
|
||||
await withBrowser(async (response, context) => {
|
||||
assert.strictEqual(context.getSelectedPageIdx(), 0);
|
||||
|
||||
Reference in new issue
Block a user