chromedevtools--chrome-devtools-mcp
7548c97663
Enables "third-party developer tools" feature. This allows the inspected web page to expose tools which provide debugging information to Chrome DevTools for Agents. Third-party developer tools enable web applications to expose internal state, component hierarchies, or specific debug data that cannot be deduced through static analysis. This allows Chrome DevTools for Agents to provide richer, more actionable context to AI agents during debugging sessions. 2 additional tools are enabled in Chrome DevTools for Agents for interacting with third-party developer tools: `list_3p_developer_tools()` and `execute_3p_developer_tool`. Code changes in this PR: - Rename "in-page tools" to "third-party developer tools" - Unhide - Make available in CLI - Add documentation
818 行
24 KiB
TypeScript
818 行
24 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import assert from 'node:assert';
|
|
import {describe, it} from 'node:test';
|
|
|
|
import sinon from 'sinon';
|
|
|
|
import type {ParsedArguments} from '../../src/bin/chrome-devtools-mcp-cli-options.js';
|
|
import type {McpContext} from '../../src/McpContext.js';
|
|
import type {McpResponse} from '../../src/McpResponse.js';
|
|
import {TextSnapshot} from '../../src/TextSnapshot.js';
|
|
import {
|
|
executeThirdPartyDeveloperTool,
|
|
listThirdPartyDeveloperTools,
|
|
} from '../../src/tools/thirdPartyDeveloper.js';
|
|
import type {
|
|
ToolGroup,
|
|
ToolDefinition,
|
|
} from '../../src/tools/thirdPartyDeveloper.js';
|
|
import {withMcpContext} from '../utils.js';
|
|
|
|
describe('thirdPartyDeveloperTools', () => {
|
|
describe('list_3p_developer_tools', () => {
|
|
it('lists tools', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
arg: {type: 'string'},
|
|
},
|
|
},
|
|
execute: () => 'result',
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await listThirdPartyDeveloperTools.handler(
|
|
{params: {}, page},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
const result = await response.handle(
|
|
'list_3p_developer_tools',
|
|
context,
|
|
);
|
|
// @ts-expect-error `structuredContent` has `thirdPartyDeveloperTools`
|
|
const actualGroup = result.structuredContent.thirdPartyDeveloperTools;
|
|
assert.strictEqual(actualGroup.name, 'test-group');
|
|
assert.strictEqual(actualGroup.description, 'test description');
|
|
assert.strictEqual(actualGroup.tools.length, 1);
|
|
assert.strictEqual(actualGroup.tools[0].name, 'test-tool');
|
|
assert.strictEqual(
|
|
actualGroup.tools[0].description,
|
|
'test tool description',
|
|
);
|
|
assert.deepEqual(actualGroup.tools[0].inputSchema, {
|
|
type: 'object',
|
|
properties: {
|
|
arg: {type: 'string'},
|
|
},
|
|
});
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('handles empty response', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
await page.pptrPage.evaluate(() => {
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith({});
|
|
});
|
|
});
|
|
|
|
await listThirdPartyDeveloperTools.handler(
|
|
{params: {}, page},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
const result = await response.handle(
|
|
'list_3p_developer_tools',
|
|
context,
|
|
);
|
|
assert.ok('thirdPartyDeveloperTools' in result.structuredContent);
|
|
assert.deepEqual(
|
|
(
|
|
result.structuredContent as {
|
|
thirdPartyDeveloperTools: ToolGroup<ToolDefinition>;
|
|
}
|
|
).thirdPartyDeveloperTools,
|
|
{},
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('handles no response', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
await page.pptrPage.evaluate(() => {
|
|
window.addEventListener('devtoolstooldiscovery', () => {
|
|
// do nothing
|
|
});
|
|
});
|
|
|
|
await listThirdPartyDeveloperTools.handler(
|
|
{params: {}, page},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
const result = await response.handle(
|
|
'list_3p_developer_tools',
|
|
context,
|
|
);
|
|
assert.ok('thirdPartyDeveloperTools' in result.structuredContent);
|
|
assert.strictEqual(
|
|
(
|
|
result.structuredContent as {
|
|
thirdPartyDeveloperTools: ToolGroup<ToolDefinition>;
|
|
}
|
|
).thirdPartyDeveloperTools,
|
|
undefined,
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('handles no eventListener', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
await listThirdPartyDeveloperTools.handler(
|
|
{params: {}, page},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
const result = await response.handle(
|
|
'list_3p_developer_tools',
|
|
context,
|
|
);
|
|
assert.ok('thirdPartyDeveloperTools' in result.structuredContent);
|
|
assert.strictEqual(
|
|
(result.structuredContent as {thirdPartyDeveloperTools: undefined})
|
|
.thirdPartyDeveloperTools,
|
|
undefined,
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('execute_3p_developer_tool', () => {
|
|
async function setupThirdPartyDeveloperTools(
|
|
response: McpResponse,
|
|
context: McpContext,
|
|
evaluateFn: () => void,
|
|
) {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
await page.pptrPage.evaluate(evaluateFn);
|
|
await listThirdPartyDeveloperTools.handler(
|
|
{params: {}, page},
|
|
response,
|
|
context,
|
|
);
|
|
await response.handle('list_3p_developer_tools', context);
|
|
}
|
|
|
|
it('executes a tool', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
arg: {type: 'string'},
|
|
},
|
|
required: ['arg'],
|
|
},
|
|
execute: () => 'result',
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({arg: 'value'}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify('result', null, 2),
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('throws if tool not found in list', async () => {
|
|
await withMcpContext(async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'missing-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
},
|
|
{message: /Tool missing-tool not found/},
|
|
);
|
|
});
|
|
});
|
|
|
|
it('throws if parameters are invalid', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
arg: {type: 'string'},
|
|
},
|
|
required: ['arg'],
|
|
},
|
|
execute: () => 'result',
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await assert.rejects(
|
|
async () => {
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}), // Missing required 'arg'
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
},
|
|
{message: /Invalid parameters for tool test-tool/},
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('handles JSON result', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
execute: () => ({foo: 'bar'}),
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify({foo: 'bar'}, null, 2),
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('replaces uid with element handle in params', async () => {
|
|
await withMcpContext(async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
|
|
page.thirdPartyDeveloperTools = {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
element: {type: 'object'},
|
|
},
|
|
required: ['element'],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
window.__dtmcp = {
|
|
executeTool: async (
|
|
_name: string,
|
|
args: Record<string, unknown>,
|
|
) => {
|
|
const el = args.element;
|
|
if (el instanceof HTMLElement) {
|
|
return {
|
|
isElement: true,
|
|
tagName: el.tagName,
|
|
id: el.id,
|
|
};
|
|
}
|
|
return {
|
|
isElement: false,
|
|
tagName: '',
|
|
id: '',
|
|
};
|
|
},
|
|
};
|
|
});
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
const div = document.createElement('div');
|
|
div.id = 'test-id';
|
|
document.body.appendChild(div);
|
|
});
|
|
|
|
const handle = await page.pptrPage.$('#test-id');
|
|
if (!handle) {
|
|
throw new Error('Handle not found');
|
|
}
|
|
|
|
page.getElementByUid = async (uid: string) => {
|
|
if (uid === 'some-uid') {
|
|
return handle;
|
|
}
|
|
throw new Error('Not found');
|
|
};
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({element: {uid: 'some-uid'}}),
|
|
},
|
|
page: page,
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify(
|
|
{
|
|
isElement: true,
|
|
tagName: 'DIV',
|
|
id: 'test-id',
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
});
|
|
});
|
|
|
|
it('processToolResult replaces functions with "<Function object>"', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
execute: () => ({
|
|
foo: 'bar',
|
|
func: () => undefined,
|
|
}),
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify({foo: 'bar', func: '<Function object>'}, null, 2),
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('processToolResult replaces circular references with "<Circular reference>"', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
execute: () => {
|
|
const obj: Record<string, unknown> = {foo: 'bar'};
|
|
obj.self = obj;
|
|
return obj;
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify({foo: 'bar', self: '<Circular reference>'}, null, 2),
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('processToolResult replaces non-plain objects with "<ConstructorName instance>"', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
await setupThirdPartyDeveloperTools(response, context, () => {
|
|
class CustomClass {
|
|
val = 'value';
|
|
}
|
|
window.__dtmcp = {
|
|
toolGroup: {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
execute: () => ({
|
|
foo: 'bar',
|
|
custom: new CustomClass(),
|
|
}),
|
|
},
|
|
],
|
|
},
|
|
};
|
|
window.addEventListener('devtoolstooldiscovery', (e: Event) => {
|
|
// @ts-expect-error Event has `respondWith`
|
|
e.respondWith(window.__dtmcp?.toolGroup);
|
|
});
|
|
});
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: context.getSelectedMcpPage(),
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify(
|
|
{foo: 'bar', custom: '<CustomClass instance>'},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('stashDOMElement stashes elements and returns UID', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
|
|
page.thirdPartyDeveloperTools = {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
window.__dtmcp = {
|
|
executeTool: async () => {
|
|
const div = document.createElement('div');
|
|
div.id = 'test-element';
|
|
document.body.appendChild(div);
|
|
return div;
|
|
},
|
|
};
|
|
});
|
|
|
|
const stub = sinon
|
|
.stub(page, 'resolveCdpElementId')
|
|
.returns('mock-uid');
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: page,
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify({uid: 'mock-uid'}, null, 2),
|
|
);
|
|
|
|
stub.restore();
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('creates a new snapshot if the third-party developer tool response contains a DOM element', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
|
|
page.thirdPartyDeveloperTools = {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
window.__dtmcp = {
|
|
executeTool: async () => {
|
|
const div = document.createElement('div');
|
|
div.id = 'test-element';
|
|
document.body.appendChild(div);
|
|
return div;
|
|
},
|
|
};
|
|
});
|
|
|
|
const stubSnapshot = sinon
|
|
.stub(TextSnapshot, 'create')
|
|
.resolves({} as TextSnapshot);
|
|
|
|
const stubResolve = sinon
|
|
.stub(page, 'resolveCdpElementId')
|
|
.returns('mock-uid');
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: page,
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
assert.ok(
|
|
stubSnapshot.calledOnce,
|
|
'Expected TextSnapshot.create to be called',
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify({uid: 'mock-uid'}, null, 2),
|
|
);
|
|
|
|
stubResolve.restore();
|
|
stubSnapshot.restore();
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
|
|
it('does not create a new snapshot if the third-party developer tool response does not contain a DOM element', async () => {
|
|
await withMcpContext(
|
|
async (response, context) => {
|
|
const page = await context.newPage();
|
|
response.setPage(page);
|
|
|
|
page.thirdPartyDeveloperTools = {
|
|
name: 'test-group',
|
|
description: 'test description',
|
|
tools: [
|
|
{
|
|
name: 'test-tool',
|
|
description: 'test tool description',
|
|
inputSchema: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
await page.pptrPage.evaluate(() => {
|
|
window.__dtmcp = {
|
|
executeTool: async () => {
|
|
return 'simple-result';
|
|
},
|
|
};
|
|
});
|
|
|
|
const stubSnapshot = sinon
|
|
.stub(TextSnapshot, 'create')
|
|
.resolves({} as TextSnapshot);
|
|
|
|
await executeThirdPartyDeveloperTool.handler(
|
|
{
|
|
params: {
|
|
toolName: 'test-tool',
|
|
params: JSON.stringify({}),
|
|
},
|
|
page: page,
|
|
},
|
|
response,
|
|
context,
|
|
);
|
|
|
|
assert.ok(
|
|
stubSnapshot.notCalled,
|
|
'Expected TextSnapshot.create not to be called',
|
|
);
|
|
assert.strictEqual(
|
|
response.responseLines[0],
|
|
JSON.stringify('simple-result', null, 2),
|
|
);
|
|
|
|
stubSnapshot.restore();
|
|
},
|
|
undefined,
|
|
{categoryExperimentalThirdParty: true} as ParsedArguments,
|
|
);
|
|
});
|
|
});
|
|
});
|