chore: show download link on the status mismatch page (#928)
<img width="610" height="108" alt="image" src="https://github.com/user-attachments/assets/bc1f7534-f282-44f0-bb58-e385b2bf82af" />
This commit is contained in:
@@ -193,3 +193,14 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Link-style button */
|
||||||
|
.link-button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #0066cc;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ type Status =
|
|||||||
| { type: 'connecting'; message: string }
|
| { type: 'connecting'; message: string }
|
||||||
| { type: 'connected'; message: string }
|
| { type: 'connected'; message: string }
|
||||||
| { type: 'error'; message: string }
|
| { type: 'error'; message: string }
|
||||||
| { type: 'error'; versionMismatch: { pwMcpVersion: string; extensionVersion: string } };
|
| { type: 'error'; versionMismatch: { pwMcpVersion: string; extensionVersion: string; downloadUrl: string } };
|
||||||
|
|
||||||
const ConnectApp: React.FC = () => {
|
const ConnectApp: React.FC = () => {
|
||||||
const [tabs, setTabs] = useState<TabInfo[]>([]);
|
const [tabs, setTabs] = useState<TabInfo[]>([]);
|
||||||
@@ -61,13 +61,15 @@ const ConnectApp: React.FC = () => {
|
|||||||
const pwMcpVersion = params.get('pwMcpVersion');
|
const pwMcpVersion = params.get('pwMcpVersion');
|
||||||
const extensionVersion = chrome.runtime.getManifest().version;
|
const extensionVersion = chrome.runtime.getManifest().version;
|
||||||
if (pwMcpVersion !== extensionVersion) {
|
if (pwMcpVersion !== extensionVersion) {
|
||||||
|
const downloadUrl = params.get('downloadUrl') || `https://github.com/microsoft/playwright-mcp/releases/download/v${extensionVersion}/playwright-mcp-extension-v${extensionVersion}.zip`;
|
||||||
setShowButtons(false);
|
setShowButtons(false);
|
||||||
setShowTabList(false);
|
setShowTabList(false);
|
||||||
setStatus({
|
setStatus({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
versionMismatch: {
|
versionMismatch: {
|
||||||
pwMcpVersion: pwMcpVersion || 'unknown',
|
pwMcpVersion: pwMcpVersion || 'unknown',
|
||||||
extensionVersion
|
extensionVersion,
|
||||||
|
downloadUrl
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -176,13 +178,34 @@ const ConnectApp: React.FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const VersionMismatchError: React.FC<{ pwMcpVersion: string; extensionVersion: string }> = ({ pwMcpVersion, extensionVersion }) => {
|
const VersionMismatchError: React.FC<{ pwMcpVersion: string; extensionVersion: string; downloadUrl: string }> = ({ pwMcpVersion, extensionVersion, downloadUrl }) => {
|
||||||
const readmeUrl = 'https://github.com/microsoft/playwright-mcp/blob/main/extension/README.md';
|
const readmeUrl = 'https://github.com/microsoft/playwright-mcp/blob/main/extension/README.md';
|
||||||
|
|
||||||
|
const handleDownloadAndOpenExtensions = () => {
|
||||||
|
// Start download
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = downloadUrl;
|
||||||
|
link.download = `playwright-mcp-extension-v${extensionVersion}.zip`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
|
||||||
|
if (tabs[0]?.id)
|
||||||
|
chrome.tabs.update(tabs[0].id, { url: 'chrome://extensions/' });
|
||||||
|
});
|
||||||
|
}, 1000); // Wait 1 second for download to initiate
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
Incompatible Playwright MCP version: {pwMcpVersion} (extension version: {extensionVersion}).
|
Incompatible Playwright MCP version: {pwMcpVersion} (extension version: {extensionVersion}).{' '}
|
||||||
Please install the latest version of the extension.{' '}
|
<button
|
||||||
See <a href={readmeUrl} target='_blank' rel='noopener noreferrer'>installation instructions</a>.
|
onClick={handleDownloadAndOpenExtensions}
|
||||||
|
className='link-button'
|
||||||
|
>Click here</button> to download the matching extension, then drag and drop it into the Chrome Extensions page.{' '}
|
||||||
|
See <a href={readmeUrl} target='_blank' rel='noopener noreferrer'>installation instructions</a> for more details.
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -191,7 +214,11 @@ const StatusBanner: React.FC<{ status: Status }> = ({ status }) => {
|
|||||||
return (
|
return (
|
||||||
<div className={`status-banner ${status.type}`}>
|
<div className={`status-banner ${status.type}`}>
|
||||||
{'versionMismatch' in status ? (
|
{'versionMismatch' in status ? (
|
||||||
<VersionMismatchError pwMcpVersion={status.versionMismatch.pwMcpVersion} extensionVersion={status.versionMismatch.extensionVersion} />
|
<VersionMismatchError
|
||||||
|
pwMcpVersion={status.versionMismatch.pwMcpVersion}
|
||||||
|
extensionVersion={status.versionMismatch.extensionVersion}
|
||||||
|
downloadUrl={status.versionMismatch.downloadUrl}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
status.message
|
status.message
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -233,12 +233,18 @@ 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. See installation instructions.`);
|
await expect(confirmationPage.locator('.status-banner')).toHaveText(`Incompatible Playwright MCP version: ${packageJSON.version} (extension version: 0.0.1). Click here to download the matching extension, then drag and drop it into the Chrome Extensions page. See installation instructions for more details.`);
|
||||||
|
|
||||||
expect(await navigateResponse).toHaveResponse({
|
expect(await navigateResponse).toHaveResponse({
|
||||||
result: expect.stringContaining('Extension connection timeout.'),
|
result: expect.stringContaining('Extension connection timeout.'),
|
||||||
isError: true,
|
isError: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const downloadPromise = confirmationPage.waitForEvent('download');
|
||||||
|
await confirmationPage.locator('.status-banner').getByRole('button', { name: 'Click here' }).click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
expect(download.url()).toBe(`https://github.com/microsoft/playwright-mcp/releases/download/v0.0.1/playwright-mcp-extension-v0.0.1.zip`);
|
||||||
|
await download.cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user