diff --git a/src/tools/pages.ts b/src/tools/pages.ts index b0bf49970..6b8d4b739 100644 --- a/src/tools/pages.ts +++ b/src/tools/pages.ts @@ -211,6 +211,22 @@ export const resizePage = defineTool({ handler: async (request, response, context) => { const page = context.getSelectedPage(); + try { + const browser = page.browser(); + const windowId = await page.windowId(); + + const bounds = await browser.getWindowBounds(windowId); + + if (bounds.windowState === 'fullscreen') { + // Have to call this twice on Ubuntu when the window is in fullscreen mode. + await browser.setWindowBounds(windowId, {windowState: 'normal'}); + await browser.setWindowBounds(windowId, {windowState: 'normal'}); + } else if (bounds.windowState !== 'normal') { + await browser.setWindowBounds(windowId, {windowState: 'normal'}); + } + } catch { + // Window APIs are not supported on all platforms + } await page.resize({ contentWidth: request.params.width, contentHeight: request.params.height, diff --git a/tests/tools/pages.test.ts b/tests/tools/pages.test.ts index c284538d7..7bf7e747d 100644 --- a/tests/tools/pages.test.ts +++ b/tests/tools/pages.test.ts @@ -214,7 +214,7 @@ describe('pages', () => { }); }); describe('resize', () => { - it('create a page', async () => { + it('resize the page', async () => { await withMcpContext(async (response, context) => { const page = context.getSelectedPage(); const resizePromise = page.evaluate(() => { @@ -228,12 +228,139 @@ describe('pages', () => { context, ); await resizePromise; + await page.waitForFunction( + () => window.innerWidth === 700 && window.innerHeight === 500, + ); const dimensions = await page.evaluate(() => { return [window.innerWidth, window.innerHeight]; }); assert.deepStrictEqual(dimensions, [700, 500]); }); }); + + it('resize when window state is normal', async () => { + await withMcpContext(async (response, context) => { + const page = context.getSelectedPage(); + const browser = page.browser(); + const windowId = await page.windowId(); + await browser.setWindowBounds(windowId, {windowState: 'normal'}); + + const {windowState} = await browser.getWindowBounds(windowId); + assert.strictEqual(windowState, 'normal'); + + const resizePromise = page.evaluate(() => { + return new Promise(resolve => { + window.addEventListener('resize', resolve, {once: true}); + }); + }); + await resizePage.handler( + {params: {width: 650, height: 450}}, + response, + context, + ); + await resizePromise; + await page.waitForFunction( + () => window.innerWidth === 650 && window.innerHeight === 450, + ); + const dimensions = await page.evaluate(() => { + return [window.innerWidth, window.innerHeight]; + }); + assert.deepStrictEqual(dimensions, [650, 450]); + }); + }); + + it('resize when window state is minimized', async () => { + await withMcpContext(async (response, context) => { + const page = context.getSelectedPage(); + const browser = page.browser(); + const windowId = await page.windowId(); + await browser.setWindowBounds(windowId, {windowState: 'minimized'}); + + const {windowState} = await browser.getWindowBounds(windowId); + assert.strictEqual(windowState, 'minimized'); + + const resizePromise = page.evaluate(() => { + return new Promise(resolve => { + window.addEventListener('resize', resolve, {once: true}); + }); + }); + await resizePage.handler( + {params: {width: 750, height: 550}}, + response, + context, + ); + await resizePromise; + await page.waitForFunction( + () => window.innerWidth === 750 && window.innerHeight === 550, + ); + const dimensions = await page.evaluate(() => { + return [window.innerWidth, window.innerHeight]; + }); + assert.deepStrictEqual(dimensions, [750, 550]); + }); + }); + + it('resize when window state is maximized', async () => { + await withMcpContext(async (response, context) => { + const page = context.getSelectedPage(); + const browser = page.browser(); + const windowId = await page.windowId(); + await browser.setWindowBounds(windowId, {windowState: 'maximized'}); + + const {windowState} = await browser.getWindowBounds(windowId); + assert.strictEqual(windowState, 'maximized'); + + const resizePromise = page.evaluate(() => { + return new Promise(resolve => { + window.addEventListener('resize', resolve, {once: true}); + }); + }); + await resizePage.handler( + {params: {width: 725, height: 525}}, + response, + context, + ); + await resizePromise; + await page.waitForFunction( + () => window.innerWidth === 725 && window.innerHeight === 525, + ); + const dimensions = await page.evaluate(() => { + return [window.innerWidth, window.innerHeight]; + }); + assert.deepStrictEqual(dimensions, [725, 525]); + }); + }); + + it('resize when window state is fullscreen', async () => { + await withMcpContext(async (response, context) => { + const page = context.getSelectedPage(); + const browser = page.browser(); + const windowId = await page.windowId(); + await browser.setWindowBounds(windowId, {windowState: 'fullscreen'}); + + const {windowState} = await browser.getWindowBounds(windowId); + assert.strictEqual(windowState, 'fullscreen'); + + const resizePromise = page.evaluate(() => { + return new Promise(resolve => { + window.addEventListener('resize', resolve, {once: true}); + }); + }); + await resizePage.handler( + {params: {width: 850, height: 650}}, + response, + context, + ); + await resizePromise; + await page.waitForFunction( + () => window.innerWidth === 850 && window.innerHeight === 650, + ); + const dimensions = await page.evaluate(() => { + return [window.innerWidth, window.innerHeight]; + }); + assert.deepStrictEqual(dimensions, [850, 650]); + }); + }); }); describe('dialogs', () => { diff --git a/tests/utils.ts b/tests/utils.ts index 6e480ffbb..1c73fc5be 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -55,6 +55,7 @@ export async function withBrowser( devtools: options.autoOpenDevTools ?? false, pipe: true, handleDevToolsAsPage: true, + args: ['--screen-info={3840x2160}'], }; const key = JSON.stringify(launchOptions);