chore: check version in page, link to instructions (#918)
This commit is contained in:
@@ -19,7 +19,6 @@ import { RelayConnection, debugLog } from './relayConnection.js';
|
|||||||
type PageMessage = {
|
type PageMessage = {
|
||||||
type: 'connectToMCPRelay';
|
type: 'connectToMCPRelay';
|
||||||
mcpRelayUrl: string;
|
mcpRelayUrl: string;
|
||||||
pwMcpVersion: string | null;
|
|
||||||
} | {
|
} | {
|
||||||
type: 'getTabs';
|
type: 'getTabs';
|
||||||
} | {
|
} | {
|
||||||
@@ -50,7 +49,7 @@ class TabShareExtension {
|
|||||||
private _onMessage(message: PageMessage, sender: chrome.runtime.MessageSender, sendResponse: (response: any) => void) {
|
private _onMessage(message: PageMessage, sender: chrome.runtime.MessageSender, sendResponse: (response: any) => void) {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'connectToMCPRelay':
|
case 'connectToMCPRelay':
|
||||||
this._connectToRelay(sender.tab!.id!, message.mcpRelayUrl, message.pwMcpVersion).then(
|
this._connectToRelay(sender.tab!.id!, message.mcpRelayUrl).then(
|
||||||
() => sendResponse({ success: true }),
|
() => sendResponse({ success: true }),
|
||||||
(error: any) => sendResponse({ success: false, error: error.message }));
|
(error: any) => sendResponse({ success: false, error: error.message }));
|
||||||
return true;
|
return true;
|
||||||
@@ -78,11 +77,7 @@ class TabShareExtension {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _connectToRelay(selectorTabId: number, mcpRelayUrl: string, pwMcpVersion: string | null): Promise<void> {
|
private async _connectToRelay(selectorTabId: number, mcpRelayUrl: string): Promise<void> {
|
||||||
const version = chrome.runtime.getManifest().version;
|
|
||||||
if (pwMcpVersion !== version)
|
|
||||||
throw new Error(`Incompatible Playwright MCP version: ${pwMcpVersion} (extension version: ${version}). Please install the latest version of the extension.`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
debugLog(`Connecting to relay at ${mcpRelayUrl}`);
|
debugLog(`Connecting to relay at ${mcpRelayUrl}`);
|
||||||
const socket = new WebSocket(mcpRelayUrl);
|
const socket = new WebSocket(mcpRelayUrl);
|
||||||
|
|||||||
@@ -19,11 +19,15 @@ import { createRoot } from 'react-dom/client';
|
|||||||
import { Button, TabItem } from './tabItem.js';
|
import { Button, TabItem } from './tabItem.js';
|
||||||
import type { TabInfo } from './tabItem.js';
|
import type { TabInfo } from './tabItem.js';
|
||||||
|
|
||||||
type StatusType = 'connected' | 'error' | 'connecting';
|
type Status =
|
||||||
|
| { type: 'connecting'; message: string }
|
||||||
|
| { type: 'connected'; message: string }
|
||||||
|
| { type: 'error'; message: string }
|
||||||
|
| { type: 'error'; versionMismatch: { pwMcpVersion: string; extensionVersion: string } };
|
||||||
|
|
||||||
const ConnectApp: React.FC = () => {
|
const ConnectApp: React.FC = () => {
|
||||||
const [tabs, setTabs] = useState<TabInfo[]>([]);
|
const [tabs, setTabs] = useState<TabInfo[]>([]);
|
||||||
const [status, setStatus] = useState<{ type: StatusType; message: string } | null>(null);
|
const [status, setStatus] = useState<Status | null>(null);
|
||||||
const [showButtons, setShowButtons] = useState(true);
|
const [showButtons, setShowButtons] = useState(true);
|
||||||
const [showTabList, setShowTabList] = useState(true);
|
const [showTabList, setShowTabList] = useState(true);
|
||||||
const [clientInfo, setClientInfo] = useState('unknown');
|
const [clientInfo, setClientInfo] = useState('unknown');
|
||||||
@@ -54,7 +58,22 @@ const ConnectApp: React.FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectToMCPRelay(relayUrl, params.get('pwMcpVersion'));
|
const pwMcpVersion = params.get('pwMcpVersion');
|
||||||
|
const extensionVersion = chrome.runtime.getManifest().version;
|
||||||
|
if (pwMcpVersion !== extensionVersion) {
|
||||||
|
setShowButtons(false);
|
||||||
|
setShowTabList(false);
|
||||||
|
setStatus({
|
||||||
|
type: 'error',
|
||||||
|
versionMismatch: {
|
||||||
|
pwMcpVersion: pwMcpVersion || 'unknown',
|
||||||
|
extensionVersion
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectToMCPRelay(relayUrl);
|
||||||
void loadTabs();
|
void loadTabs();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -64,8 +83,9 @@ const ConnectApp: React.FC = () => {
|
|||||||
setStatus({ type: 'error', message });
|
setStatus({ type: 'error', message });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const connectToMCPRelay = useCallback(async (mcpRelayUrl: string, pwMcpVersion: string | null) => {
|
const connectToMCPRelay = useCallback(async (mcpRelayUrl: string) => {
|
||||||
const response = await chrome.runtime.sendMessage({ type: 'connectToMCPRelay', mcpRelayUrl, pwMcpVersion });
|
|
||||||
|
const response = await chrome.runtime.sendMessage({ type: 'connectToMCPRelay', mcpRelayUrl });
|
||||||
if (!response.success)
|
if (!response.success)
|
||||||
handleReject(response.error);
|
handleReject(response.error);
|
||||||
}, [handleReject]);
|
}, [handleReject]);
|
||||||
@@ -122,7 +142,7 @@ const ConnectApp: React.FC = () => {
|
|||||||
<div className='content-wrapper'>
|
<div className='content-wrapper'>
|
||||||
{status && (
|
{status && (
|
||||||
<div className='status-container'>
|
<div className='status-container'>
|
||||||
<StatusBanner type={status.type} message={status.message} />
|
<StatusBanner status={status} />
|
||||||
{showButtons && (
|
{showButtons && (
|
||||||
<Button variant='reject' onClick={() => handleReject('Connection rejected. This tab can be closed.')}>
|
<Button variant='reject' onClick={() => handleReject('Connection rejected. This tab can be closed.')}>
|
||||||
Reject
|
Reject
|
||||||
@@ -156,8 +176,27 @@ const ConnectApp: React.FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const StatusBanner: React.FC<{ type: StatusType; message: string }> = ({ type, message }) => {
|
const VersionMismatchError: React.FC<{ pwMcpVersion: string; extensionVersion: string }> = ({ pwMcpVersion, extensionVersion }) => {
|
||||||
return <div className={`status-banner ${type}`}>{message}</div>;
|
const readmeUrl = 'https://github.com/microsoft/playwright-mcp/blob/main/extension/README.md';
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Incompatible Playwright MCP version: {pwMcpVersion} (extension version: {extensionVersion}).
|
||||||
|
Please install the latest version of the extension.{' '}
|
||||||
|
See <a href={readmeUrl} target='_blank' rel='noopener noreferrer'>installation instructions</a>.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const StatusBanner: React.FC<{ status: Status }> = ({ status }) => {
|
||||||
|
return (
|
||||||
|
<div className={`status-banner ${status.type}`}>
|
||||||
|
{'versionMismatch' in status ? (
|
||||||
|
<VersionMismatchError pwMcpVersion={status.versionMismatch.pwMcpVersion} extensionVersion={status.versionMismatch.extensionVersion} />
|
||||||
|
) : (
|
||||||
|
status.message
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the React app
|
// Initialize the React app
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ for (const [mode, startClientMethod] of [
|
|||||||
});
|
});
|
||||||
|
|
||||||
const confirmationPage = await confirmationPagePromise;
|
const confirmationPage = await confirmationPagePromise;
|
||||||
await expect(confirmationPage.locator('.status-banner')).toHaveText(`Incompatible Playwright MCP version: ${packageJSON.version} (extension version: 0.0.1). Please install the latest version of the extension.`);
|
await expect(confirmationPage.locator('.status-banner')).toHaveText(`Incompatible Playwright MCP version: ${packageJSON.version} (extension version: 0.0.1). Please install the latest version of the extension. See installation instructions.`);
|
||||||
|
|
||||||
expect(await navigateResponse).toHaveResponse({
|
expect(await navigateResponse).toHaveResponse({
|
||||||
result: expect.stringContaining('Extension connection timeout.'),
|
result: expect.stringContaining('Extension connection timeout.'),
|
||||||
|
|||||||
Reference in New Issue
Block a user